merge by hand - fix up rejections in Documentation/DocBook/Makefile
diff --git a/CREDITS b/CREDITS
index c9068fe..3b9e160 100644
--- a/CREDITS
+++ b/CREDITS
@@ -339,7 +339,7 @@
 D: dsp56k device driver
 
 N: Ross Biro
-E: bir7@leland.Stanford.Edu
+E: ross.biro@gmail.com
 D: Original author of the Linux networking code
 
 N: Anton Blanchard
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 72dc90f..8de8a01 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -12,8 +12,6 @@
 
 00-INDEX
 	- this file.
-BK-usage/
-	- directory with info on BitKeeper.
 BUG-HUNTING
 	- brute force method of doing binary search of patches to find bug.
 Changes
diff --git a/Documentation/BK-usage/00-INDEX b/Documentation/BK-usage/00-INDEX
deleted file mode 100644
index 8276878..0000000
--- a/Documentation/BK-usage/00-INDEX
+++ /dev/null
@@ -1,51 +0,0 @@
-bk-kernel-howto.txt: Description of kernel workflow under BitKeeper
-
-bk-make-sum: Create summary of changesets in one repository and not
-another, typically in preparation to be sent to an upstream maintainer.
-Typical usage:
-	cd my-updated-repo
-	bk-make-sum ~/repo/original-repo
-	mv /tmp/linus.txt ../original-repo.txt
-
-bksend: Create readable text output containing summary of changes, GNU
-patch of the changes, and BK metadata of changes (as needed for proper
-importing into BitKeeper by an upstream maintainer).  This output is
-suitable for emailing BitKeeper changes.  The recipient of this output
-may pipe it directly to 'bk receive'.
-
-bz64wrap: helper script. Uncompressed input is piped to this script,
-which compresses its input, and then outputs the uu-/base64-encoded
-version of the compressed input.
-
-cpcset: Copy changeset between unrelated repositories.
-Attempts to preserve changeset user, user address, description, in
-addition to the changeset (the patch) itself.
-Typical usage:
-	cd my-updated-repo
-	bk changes	# looking for a changeset...
-	cpcset 1.1511 . ../another-repo
-
-csets-to-patches: Produces a delta of two BK repositories, in the form
-of individual files, each containing a single cset as a GNU patch.
-Output is several files, each with the filename "/tmp/rev-$REV.patch"
-Typical usage:
-	cd my-updated-repo
-	bk changes -L ~/repo/original-repo 2>&1 | \
-		perl csets-to-patches
-
-cset-to-linus: Produces a delta of two BK repositories, in the form of
-changeset descriptions, with 'diffstat' output created for each
-individual changset.
-Typical usage:
-	cd my-updated-repo
-	bk changes -L ~/repo/original-repo 2>&1 | \
-		perl cset-to-linus > summary.txt
-
-gcapatch:  Generates patch containing changes in local repository.
-Typical usage:
-	cd my-updated-repo
-	gcapatch > foo.patch
-
-unbz64wrap: Reverse an encoded, compressed data stream created by
-bz64wrap into an uncompressed, typically text/plain output.
-
diff --git a/Documentation/BK-usage/bk-kernel-howto.txt b/Documentation/BK-usage/bk-kernel-howto.txt
deleted file mode 100644
index b7b9075..0000000
--- a/Documentation/BK-usage/bk-kernel-howto.txt
+++ /dev/null
@@ -1,283 +0,0 @@
-
-		   Doing the BK Thing, Penguin-Style
-
-
-
-
-This set of notes is intended mainly for kernel developers, occasional
-or full-time, but sysadmins and power users may find parts of it useful
-as well.  It assumes at least a basic familiarity with CVS, both at a
-user level (use on the cmd line) and at a higher level (client-server model).
-Due to the author's background, an operation may be described in terms
-of CVS, or in terms of how that operation differs from CVS.
-
-This is -not- intended to be BitKeeper documentation.  Always run
-"bk help <command>" or in X "bk helptool <command>" for reference
-documentation.
-
-
-BitKeeper Concepts
-------------------
-
-In the true nature of the Internet itself, BitKeeper is a distributed
-system.  When applied to revision control, this means doing away with
-client-server, and changing to a parent-child model... essentially
-peer-to-peer.  On the developer's end, this also represents a
-fundamental disruption in the standard workflow of changes, commits,
-and merges.  You will need to take a few minutes to think about
-how to best work under BitKeeper, and re-optimize things a bit.
-In some sense it is a bit radical, because it might described as
-tossing changes out into a maelstrom and having them magically
-land at the right destination... but I'm getting ahead of myself.
-
-Let's start with this progression:
-Each BitKeeper source tree on disk is a repository unto itself.
-Each repository has a parent (except the root/original, of course).
-Each repository contains a set of a changesets ("csets").
-Each cset is one or more changed files, bundled together.
-
-Each tree is a repository, so all changes are checked into the local
-tree.  When a change is checked in, all modified files are grouped
-into a logical unit, the changeset.  Internally, BK links these
-changesets in a tree, representing various converging and diverging
-lines of development.  These changesets are the bread and butter of
-the BK system.
-
-After the concept of changesets, the next thing you need to get used
-to is having multiple copies of source trees lying around.  This -really-
-takes some getting used to, for some people.  Separate source trees
-are the means in BitKeeper by which you delineate parallel lines
-of development, both minor and major.  What would be branches in
-CVS become separate source trees, or "clones" in BitKeeper [heh,
-or Star Wars] terminology.
-
-Clones and changesets are the tools from which most of the power of
-BitKeeper is derived.  As mentioned earlier, each clone has a parent,
-the tree used as the source when the new clone was created.  In a
-CVS-like setup, the parent would be a remote server on the Internet,
-and the child is your local clone of that tree.
-
-Once you have established a common baseline between two source trees --
-a common parent -- then you can merge changesets between those two
-trees with ease.  Merging changes into a tree is called a "pull", and
-is analagous to 'cvs update'.  A pull downloads all the changesets in
-the remote tree you do not have, and merges them.  Sending changes in
-one tree to another tree is called a "push".  Push sends all changes
-in the local tree the remote does not yet have, and merges them.
-
-From these concepts come some initial command examples:
-
-1) bk clone -q http://linux.bkbits.net/linux-2.5 linus-2.5
-Download a 2.5 stock kernel tree, naming it "linus-2.5" in the local dir.
-The "-q" disables listing every single file as it is downloaded.
-
-2) bk clone -ql linus-2.5 alpha-2.5
-Create a separate source tree for the Alpha AXP architecture.
-The "-l" uses hard links instead of copying data, since both trees are
-on the local disk.  You can also replace the above with "bk lclone -q ..."
-
-You only clone a tree -once-.  After cloning the tree lives a long time
-on disk, being updating by pushes and pulls.
-
-3) cd alpha-2.5 ; bk pull http://gkernel.bkbits.net/alpha-2.5
-Download changes in "alpha-2.5" repository which are not present
-in the local repository, and merge them into the source tree.
-
-4) bk -r co -q
-Because every tree is a repository, files must be checked out before
-they will be in their standard places in the source tree.
-
-5)	bk vi fs/inode.c				# example change...
-	bk citool					# checkin, using X tool
-	bk push bk://gkernel@bkbits.net/alpha-2.5	# upload change
-Typical example of a BK sequence that would replace the analagous CVS
-situation,
-	vi fs/inode.c
-	cvs commit
-
-As this is just supposed to be a quick BK intro, for more in-depth
-tutorials, live working demos, and docs, see http://www.bitkeeper.com/
-
-
-
-BK and Kernel Development Workflow
-----------------------------------
-Currently the latest 2.5 tree is available via "bk clone $URL"
-and "bk pull $URL" at http://linux.bkbits.net/linux-2.5
-This should change in a few weeks to a kernel.org URL.
-
-
-A big part of using BitKeeper is organizing the various trees you have
-on your local disk, and organizing the flow of changes among those
-trees, and remote trees.  If one were to graph the relationships between
-a desired BK setup, you are likely to see a few-many-few graph, like
-this:
-
-		    linux-2.5
-		        |
-	       merge-to-linus-2.5
-		 /    |      |
-	        /     |      |
-	vm-hacks  bugfixes  filesys   personal-hacks
-	      \	      |	     |		/
-	       \      |      |         /
-		\     |      |        /
-	         testing-and-validation
-
-Since a "bk push" sends all changes not in the target tree, and
-since a "bk pull" receives all changes not in the source tree, you want
-to make sure you are only pushing specific changes to the desired tree,
-not all changes from "peer parent" trees.  For example, pushing a change
-from the testing-and-validation tree would probably be a bad idea,
-because it will push all changes from vm-hacks, bugfixes, filesys, and
-personal-hacks trees into the target tree.
-
-One would typically work on only one "theme" at a time, either
-vm-hacks or bugfixes or filesys, keeping those changes isolated in
-their own tree during development, and only merge the isolated with
-other changes when going upstream (to Linus or other maintainers) or
-downstream (to your "union" trees, like testing-and-validation above).
-
-It should be noted that some of this separation is not just recommended
-practice, it's actually [for now] -enforced- by BitKeeper.  BitKeeper
-requires that changesets maintain a certain order, which is the reason
-that "bk push" sends all local changesets the remote doesn't have.  This
-separation may look like a lot of wasted disk space at first, but it
-helps when two unrelated changes may "pollute" the same area of code, or
-don't follow the same pace of development, or any other of the standard
-reasons why one creates a development branch.
-
-Small development branches (clones) will appear and disappear:
-
-	-------- A --------- B --------- C --------- D -------
-	          \                                 /
-		   -----short-term devel branch-----
-
-While long-term branches will parallel a tree (or trees), with period
-merge points.  In this first example, we pull from a tree (pulls,
-"\") periodically, such as what occurs when tracking changes in a
-vendor tree, never pushing changes back up the line:
-
-	-------- A --------- B --------- C --------- D -------
-	          \                       \           \
-	           ----long-term devel branch-----------------
-
-And then a more common case in Linux kernel development, a long term
-branch with periodic merges back into the tree (pushes, "/"):
-
-	-------- A --------- B --------- C --------- D -------
-	          \                       \         / \
-	           ----long-term devel branch-----------------
-
-
-
-
-
-Submitting Changes to Linus
----------------------------
-There's a bit of an art, or style, of submitting changes to Linus.
-Since Linus's tree is now (you might say) fully integrated into the
-distributed BitKeeper system, there are several prerequisites to
-properly submitting a BitKeeper change.  All these prereq's are just
-general cleanliness of BK usage, so as people become experts at BK, feel
-free to optimize this process further (assuming Linus agrees, of
-course).
-
-
-
-0) Make sure your tree was originally cloned from the linux-2.5 tree
-created by Linus.  If your tree does not have this as its ancestor, it
-is impossible to reliably exchange changesets.
-
-
-
-1) Pay attention to your commit text.  The commit message that
-accompanies each changeset you submit will live on forever in history,
-and is used by Linus to accurately summarize the changes in each
-pre-patch.  Remember that there is no context, so
-	"fix for new scheduler changes"
-would be too vague, but
-	"fix mips64 arch for new scheduler switch_to(), TIF_xxx semantics"
-would be much better.
-
-You can and should use the command "bk comment -C<rev>" to update the
-commit text, and improve it after the fact.  This is very useful for
-development: poor, quick descriptions during development, which get
-cleaned up using "bk comment" before issuing the "bk push" to submit the
-changes.
-
-
-
-2) Include an Internet-available URL for Linus to pull from, such as
-
-	Pull from:  http://gkernel.bkbits.net/net-drivers-2.5
-
-
-
-3) Include a summary and "diffstat -p1" of each changeset that will be
-downloaded, when Linus issues a "bk pull".  The author auto-generates
-these summaries using "bk changes -L <parent>", to obtain a listing
-of all the pending-to-send changesets, and their commit messages.
-
-It is important to show Linus what he will be downloading when he issues
-a "bk pull", to reduce the time required to sift the changes once they
-are downloaded to Linus's local machine.
-
-IMPORTANT NOTE:  One of the features of BK is that your repository does
-not have to be up to date, in order for Linus to receive your changes.
-It is considered a courtesy to keep your repository fairly recent, to
-lessen any potential merge work Linus may need to do.
-
-
-4) Split up your changes.  Each maintainer<->Linus situation is likely
-to be slightly different here, so take this just as general advice.  The
-author splits up changes according to "themes" when merging with Linus.
-Simultaneous pushes from local development go to special trees which
-exist solely to house changes "queued" for Linus.  Example of the trees:
-
-	net-drivers-2.5 -- on-going net driver maintenance
-	vm-2.5 -- VM-related changes
-	fs-2.5 -- filesystem-related changes
-
-Linus then has much more freedom for pulling changes.  He could (for
-example) issue a "bk pull" on vm-2.5 and fs-2.5 trees, to merge their
-changes, but hold off net-drivers-2.5 because of a change that needs
-more discussion.
-
-Other maintainers may find that a single linus-pull-from tree is
-adequate for passing BK changesets to him.
-
-
-
-Frequently Answered Questions
------------------------------
-1) How do I change the e-mail address shown in the changelog?
-A. When you run "bk citool" or "bk commit", set environment
-   variables BK_USER and BK_HOST to the desired username
-   and host/domain name.
-
-
-2) How do I use tags / get a diff between two kernel versions?
-A. Pass the tags Linus uses to 'bk export'.
-
-ChangeSets are in a forward-progressing order, so it's pretty easy
-to get a snapshot starting and ending at any two points in time.
-Linus puts tags on each release and pre-release, so you could use
-these two examples:
-
-    bk export -tpatch -hdu -rv2.5.4,v2.5.5 | less
-        # creates patch-2.5.5 essentially
-    bk export -tpatch -du -rv2.5.5-pre1,v2.5.5 | less
-        # changes from pre1 to final
-
-A tag is just an alias for a specific changeset... and since changesets
-are ordered, a tag is thus a marker for a specific point in time (or
-specific state of the tree).
-
-
-3) Is there an easy way to generate One Big Patch versus mainline,
-   for my long-lived kernel branch?
-A. Yes.  This requires BK 3.x, though.
-
-	bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+
-
diff --git a/Documentation/BK-usage/bk-make-sum b/Documentation/BK-usage/bk-make-sum
deleted file mode 100755
index 58ca46a..0000000
--- a/Documentation/BK-usage/bk-make-sum
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh -e
-# DIR=$HOME/BK/axp-2.5
-# cd $DIR
-
-LINUS_REPO=$1
-DIRBASE=`basename $PWD`
-
-{
-cat <<EOT
-Please do a
-
-	bk pull bk://gkernel.bkbits.net/$DIRBASE
-
-This will update the following files:
-
-EOT
-
-bk export -tpatch -hdu -r`bk repogca $LINUS_REPO`,+ | diffstat -p1 2>/dev/null
-
-cat <<EOT
-
-through these ChangeSets:
-
-EOT
-
-bk changes -L -d'$unless(:MERGE:){ChangeSet|:CSETREV:\n}' $LINUS_REPO |
-bk -R prs -h -d'$unless(:MERGE:){<:P:@:HOST:> (:D: :I:)\n$each(:C:){   (:C:)\n}\n}' -
-
-} > /tmp/linus.txt
-
-cat <<EOT
-Mail text in /tmp/linus.txt; please check and send using your favourite
-mailer.
-EOT
diff --git a/Documentation/BK-usage/bksend b/Documentation/BK-usage/bksend
deleted file mode 100755
index 836ca94..0000000
--- a/Documentation/BK-usage/bksend
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-# A script to format BK changeset output in a manner that is easy to read.
-# Andreas Dilger <adilger@turbolabs.com>  13/02/2002
-#
-# Add diffstat output after Changelog <adilger@turbolabs.com>   21/02/2002
-
-PROG=bksend
-
-usage() {
-	echo "usage: $PROG -r<rev>"
-	echo -e "\twhere <rev> is of the form '1.23', '1.23..', '1.23..1.27',"
-	echo -e "\tor '+' to indicate the most recent revision"
-
-	exit 1
-}
-
-case $1 in
--r) REV=$2; shift ;;
--r*) REV=`echo $1 | sed 's/^-r//'` ;;
-*) echo "$PROG: no revision given, you probably don't want that";;
-esac
-
-[ -z "$REV" ] && usage
-
-echo "You can import this changeset into BK by piping this whole message to:"
-echo "'| bk receive [path to repository]' or apply the patch as usual."
-
-SEP="\n===================================================================\n\n"
-echo -e $SEP
-env PAGER=/bin/cat bk changes -r$REV
-echo
-bk export -tpatch -du -h -r$REV | diffstat
-echo; echo
-bk export -tpatch -du -h -r$REV
-echo -e $SEP
-bk send -wgzip_uu -r$REV -
diff --git a/Documentation/BK-usage/bz64wrap b/Documentation/BK-usage/bz64wrap
deleted file mode 100755
index be78087..0000000
--- a/Documentation/BK-usage/bz64wrap
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-# bz64wrap - the sending side of a bzip2 | base64 stream
-# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
-
-
-PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
-
-# A program to generate base64 encoding on stdout
-BASE64_ENCODE="uuencode -m /dev/stdout"
-BASE64_BEGIN=
-BASE64_END=
-
-BZIP=NO
-BASE64=NO
-
-# Test if we have the bzip program installed
-bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES
-
-# Test if uuencode can handle the -m (MIME) encoding option
-$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
-
-if [ $BASE64 = NO ]; then
-	BASE64_ENCODE=mimencode
-	BASE64_BEGIN="begin-base64 644 -"
-	BASE64_END="===="
-
-	$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
-fi
-
-if [ $BZIP = NO -o $BASE64 = NO ]; then
-	echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64"
-	exit 1
-fi
-
-# Sadly, mimencode does not appear to have good "begin" and "end" markers
-# like uuencode does, and it is picky about getting the right start/end of
-# the base64 stream, so we handle this internally.
-echo "$BASE64_BEGIN"
-bzip2 -9 | $BASE64_ENCODE
-echo "$BASE64_END"
diff --git a/Documentation/BK-usage/cpcset b/Documentation/BK-usage/cpcset
deleted file mode 100755
index b8faca9..0000000
--- a/Documentation/BK-usage/cpcset
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-#
-# Purpose: Copy changeset patch and description from one
-#	   repository to another, unrelated one.
-#
-# usage:  cpcset [revision] [from-repository] [to-repository]
-#
-
-REV=$1
-FROM=$2
-TO=$3
-TMPF=/tmp/cpcset.$$
-
-rm -f $TMPF*
-
-CWD_SAVE=`pwd`
-cd $FROM
-bk changes -r$REV			|	\
-	grep -v '^ChangeSet'		|	\
-	sed -e 's/^  //g' > $TMPF.log
-
-USERHOST=`bk changes -r$REV | grep '^ChangeSet' | awk '{print $4}'`
-export BK_USER=`echo $USERHOST | awk '-F@' '{print $1}'`
-export BK_HOST=`echo $USERHOST | awk '-F@' '{print $2}'`
-
-bk export -tpatch -hdu -r$REV > $TMPF.patch && \
-cd $CWD_SAVE && \
-cd $TO && \
-bk import -tpatch -CFR -y"`cat $TMPF.log`" $TMPF.patch . && \
-bk commit -y"`cat $TMPF.log`"
-
-rm -f $TMPF*
-
-echo changeset $REV copied.
-echo ""
-
diff --git a/Documentation/BK-usage/cset-to-linus b/Documentation/BK-usage/cset-to-linus
deleted file mode 100755
index d28a96f..0000000
--- a/Documentation/BK-usage/cset-to-linus
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-
-my ($lhs, $rev, $tmp, $rhs, $s);
-my @cset_text = ();
-my @pipe_text = ();
-my $have_cset = 0;
-
-while (<>) {
-	next if /^---/;
-
-	if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) {
-		&cset_rev if ($have_cset);
-
-		$rev = $tmp;
-		$have_cset = 1;
-
-		push(@cset_text, $_);
-	}
-
-	elsif ($have_cset) {
-		push(@cset_text, $_);
-	}
-}
-&cset_rev if ($have_cset);
-exit(0);
-
-
-sub cset_rev {
-	my $empty_cset = 0;
-
-	open PIPE, "bk export -tpatch -hdu -r $rev | diffstat -p1 2>/dev/null |" or die;
-	while ($s = <PIPE>) {
-		$empty_cset = 1 if ($s =~ /0 files changed/);
-		push(@pipe_text, $s);
-	}
-	close(PIPE);
-
-	if (! $empty_cset) {
-		print @cset_text;
-		print @pipe_text;
-		print "\n\n";
-	}
-
-	@pipe_text = ();
-	@cset_text = ();
-}
-
diff --git a/Documentation/BK-usage/csets-to-patches b/Documentation/BK-usage/csets-to-patches
deleted file mode 100755
index e2b81c3..0000000
--- a/Documentation/BK-usage/csets-to-patches
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-
-my ($lhs, $rev, $tmp, $rhs, $s);
-my @cset_text = ();
-my @pipe_text = ();
-my $have_cset = 0;
-
-while (<>) {
-	next if /^---/;
-
-	if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) {
-		&cset_rev if ($have_cset);
-
-		$rev = $tmp;
-		$have_cset = 1;
-
-		push(@cset_text, $_);
-	}
-
-	elsif ($have_cset) {
-		push(@cset_text, $_);
-	}
-}
-&cset_rev if ($have_cset);
-exit(0);
-
-
-sub cset_rev {
-	my $empty_cset = 0;
-
-	system("bk export -tpatch -du -r $rev > /tmp/rev-$rev.patch");
-
-	if (! $empty_cset) {
-		print @cset_text;
-		print @pipe_text;
-		print "\n\n";
-	}
-
-	@pipe_text = ();
-	@cset_text = ();
-}
-
diff --git a/Documentation/BK-usage/gcapatch b/Documentation/BK-usage/gcapatch
deleted file mode 100755
index aaeb17d..0000000
--- a/Documentation/BK-usage/gcapatch
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# Purpose: Generate GNU diff of local changes versus canonical top-of-tree
-#
-# Usage: gcapatch > foo.patch
-#
-
-bk export -tpatch -hdu -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+
diff --git a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap
deleted file mode 100755
index 4fc3e73..0000000
--- a/Documentation/BK-usage/unbz64wrap
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-# unbz64wrap - the receiving side of a bzip2 | base64 stream
-# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
-
-# Sadly, mimencode does not appear to have good "begin" and "end" markers
-# like uuencode does, and it is picky about getting the right start/end of
-# the base64 stream, so we handle this explicitly here.
-
-PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
-
-if mimencode -u < /dev/null > /dev/null 2>&1 ; then
-	SHOW=
-	while read LINE; do
-		case $LINE in
-		begin-base64*) SHOW=YES ;;
-		====) SHOW= ;;
-		*) [ "$SHOW" ] && echo "$LINE" ;;
-		esac
-	done | mimencode -u | bunzip2
-	exit $?
-else
-	cat - | uudecode -o /dev/stdout | bunzip2
-	exit $?
-fi
diff --git a/Documentation/Changes b/Documentation/Changes
index caa6a55..57542bc 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -357,14 +357,14 @@
 ----------
 o  <http://sourceforge.net/projects/linuxquota/>
 
-Jade
-----
-o  <ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz>
-
 DocBook Stylesheets
 -------------------
 o  <http://nwalsh.com/docbook/dsssl/>
 
+XMLTO XSLT Frontend
+-------------------
+o  <http://cyberelk.net/tim/xmlto/>
+
 Intel P6 microcode
 ------------------
 o  <http://www.urbanmyth.org/microcode/>
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index e69d686..87da347 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -7,11 +7,10 @@
 # list of DOCBOOKS.
 
 DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
-	    kernel-hacking.xml kernel-locking.xml via-audio.xml \
-	    deviceiobook.xml procfs-guide.xml tulip-user.xml \
-	    writing_usb_driver.xml sis900.xml kernel-api.xml \
-	    journal-api.xml lsm.xml usb.xml gadget.xml libata.xml \
-	    mtdnand.xml librs.xml
+	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
+	    procfs-guide.xml writing_usb_driver.xml \
+	    sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
+	    gadget.xml libata.xml mtdnand.xml librs.xml
 
 ###
 # The build process is as follows (targets):
@@ -42,14 +41,16 @@
 mandocs: $(MAN)
 
 installmandocs: mandocs
-	$(MAKEMAN) install Documentation/DocBook/man
+	mkdir -p /usr/local/man/man9/
+	install Documentation/DocBook/man/*.9.gz /usr/local/man/man9/
 
 ###
 #External programs used
 KERNELDOC = scripts/kernel-doc
 DOCPROC   = scripts/basic/docproc
-SPLITMAN  = $(PERL) $(srctree)/scripts/split-man
-MAKEMAN   = $(PERL) $(srctree)/scripts/makeman
+
+XMLTOFLAGS = -m Documentation/DocBook/stylesheet.xsl
+#XMLTOFLAGS += --skip-validation
 
 ###
 # DOCPROC is used for two purposes:
@@ -96,45 +97,44 @@
 # Rules to generate postscript, PDF and HTML
 # db2html creates a directory. Generate a html file used for timestamp
 
-quiet_cmd_db2ps = DB2PS   $@
-      cmd_db2ps = db2ps -o $(dir $@) $<
+quiet_cmd_db2ps = XMLTO    $@
+      cmd_db2ps = xmlto ps $(XMLTOFLAGS) -o $(dir $@) $<
 %.ps : %.xml
-	@(which db2ps > /dev/null 2>&1) || \
-	 (echo "*** You need to install DocBook stylesheets ***"; \
+	@(which xmlto > /dev/null 2>&1) || \
+	 (echo "*** You need to install xmlto ***"; \
 	  exit 1)
 	$(call cmd,db2ps)
 
-quiet_cmd_db2pdf = DB2PDF  $@
-      cmd_db2pdf = db2pdf -o $(dir $@) $<
+quiet_cmd_db2pdf = XMLTO   $@
+      cmd_db2pdf = xmlto pdf $(XMLTOFLAGS) -o $(dir $@) $<
 %.pdf : %.xml
-	@(which db2pdf > /dev/null 2>&1) || \
-	 (echo "*** You need to install DocBook stylesheets ***"; \
+	@(which xmlto > /dev/null 2>&1) || \
+	 (echo "*** You need to install xmlto ***"; \
 	  exit 1)
 	$(call cmd,db2pdf)
 
-quiet_cmd_db2html = DB2HTML $@
-      cmd_db2html = db2html -o $(patsubst %.html,%,$@) $< &&		      \
-		echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/book1.html"> \
+quiet_cmd_db2html = XMLTO  $@
+      cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \
+		echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
          Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
 
 %.html:	%.xml
-	@(which db2html > /dev/null 2>&1) || \
-	 (echo "*** You need to install DocBook stylesheets ***"; \
+	@(which xmlto > /dev/null 2>&1) || \
+	 (echo "*** You need to install xmlto ***"; \
 	  exit 1)
 	@rm -rf $@ $(patsubst %.html,%,$@)
 	$(call cmd,db2html)
 	@if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
             cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
 
-###
-# Rule to generate man files - output is placed in the man subdirectory
-
-%.9:	%.xml
-ifneq ($(KBUILD_SRC),)
-	$(Q)mkdir -p $(objtree)/Documentation/DocBook/man
-endif
-	$(SPLITMAN) $< $(objtree)/Documentation/DocBook/man "$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)"
-	$(MAKEMAN) convert $(objtree)/Documentation/DocBook/man $<
+quiet_cmd_db2man = XMLTO   $@
+      cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi
+%.9 : %.xml
+	@(which xmlto > /dev/null 2>&1) || \
+	 (echo "*** You need to install xmlto ***"; \
+	  exit 1)
+	$(call cmd,db2man)
+	@touch $@
 
 ###
 # Rules to generate postscripts and PNG imgages from .fig format files
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 1bd20c8..757cef8 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -49,13 +49,33 @@
 !Iinclude/asm-i386/unaligned.h
      </sect1>
 
-<!-- FIXME:
-  kernel/sched.c has no docs, which stuffs up the sgml.  Comment
-  out until somebody adds docs.  KAO
      <sect1><title>Delaying, scheduling, and timer routines</title>
-X!Ekernel/sched.c
+!Iinclude/linux/sched.h
+!Ekernel/sched.c
+!Ekernel/timer.c
      </sect1>
-KAO -->
+     <sect1><title>Internal Functions</title>
+!Ikernel/exit.c
+!Ikernel/signal.c
+     </sect1>
+
+     <sect1><title>Kernel objects manipulation</title>
+<!--
+X!Iinclude/linux/kobject.h
+-->
+!Elib/kobject.c
+     </sect1>
+
+     <sect1><title>Kernel utility functions</title>
+!Iinclude/linux/kernel.h
+<!-- This needs to clean up to make kernel-doc happy
+X!Ekernel/printk.c
+ -->
+!Ekernel/panic.c
+!Ekernel/sys.c
+!Ekernel/rcupdate.c
+     </sect1>
+
   </chapter>
 
   <chapter id="adt">
@@ -81,7 +101,9 @@
 !Elib/vsprintf.c
      </sect1>
      <sect1><title>String Manipulation</title>
-!Ilib/string.c
+<!-- All functions are exported at now
+X!Ilib/string.c
+ -->
 !Elib/string.c
      </sect1>
      <sect1><title>Bit Operations</title>
@@ -98,6 +120,25 @@
 !Iinclude/asm-i386/uaccess.h
 !Iarch/i386/lib/usercopy.c
      </sect1>
+     <sect1><title>More Memory Management Functions</title>
+!Iinclude/linux/rmap.h
+!Emm/readahead.c
+!Emm/filemap.c
+!Emm/memory.c
+!Emm/vmalloc.c
+!Emm/mempool.c
+!Emm/page-writeback.c
+!Emm/truncate.c
+     </sect1>
+  </chapter>
+
+
+  <chapter id="ipc">
+     <title>Kernel IPC facilities</title>
+
+     <sect1><title>IPC utilities</title>
+!Iipc/util.c
+     </sect1>
   </chapter>
 
   <chapter id="kfifo">
@@ -114,6 +155,10 @@
      <sect1><title>sysctl interface</title>
 !Ekernel/sysctl.c
      </sect1>
+
+     <sect1><title>proc filesystem interface</title>
+!Ifs/proc/base.c
+     </sect1>
   </chapter>
 
   <chapter id="debugfs">
@@ -127,6 +172,10 @@
 
   <chapter id="vfs">
      <title>The Linux VFS</title>
+     <sect1><title>The Filesystem types</title>
+!Iinclude/linux/fs.h
+!Einclude/linux/fs.h
+     </sect1>
      <sect1><title>The Directory Cache</title>
 !Efs/dcache.c
 !Iinclude/linux/dcache.h
@@ -142,13 +191,31 @@
 !Efs/locks.c
 !Ifs/locks.c
      </sect1>
+     <sect1><title>Other Functions</title>
+!Efs/mpage.c
+!Efs/namei.c
+!Efs/buffer.c
+!Efs/bio.c
+!Efs/seq_file.c
+!Efs/filesystems.c
+!Efs/fs-writeback.c
+!Efs/block_dev.c
+     </sect1>
   </chapter>
 
   <chapter id="netcore">
      <title>Linux Networking</title>
+     <sect1><title>Networking Base Types</title>
+!Iinclude/linux/net.h
+     </sect1>
      <sect1><title>Socket Buffer Functions</title>
 !Iinclude/linux/skbuff.h
+!Iinclude/net/sock.h
+!Enet/socket.c
 !Enet/core/skbuff.c
+!Enet/core/sock.c
+!Enet/core/datagram.c
+!Enet/core/stream.c
      </sect1>
      <sect1><title>Socket Filter</title>
 !Enet/core/filter.c
@@ -158,6 +225,14 @@
 !Enet/core/gen_stats.c
 !Enet/core/gen_estimator.c
      </sect1>
+     <sect1><title>SUN RPC subsystem</title>
+<!-- The !D functionality is not perfect, garbage has to be protected by comments
+!Dnet/sunrpc/sunrpc_syms.c
+-->
+!Enet/sunrpc/xdr.c
+!Enet/sunrpc/svcsock.c
+!Enet/sunrpc/sched.c
+     </sect1>
   </chapter>
 
   <chapter id="netdev">
@@ -194,11 +269,26 @@
 !Iarch/i386/kernel/irq.c
      </sect1>
 
+     <sect1><title>Resources Management</title>
+!Ekernel/resource.c
+     </sect1>
+
      <sect1><title>MTRR Handling</title>
 !Earch/i386/kernel/cpu/mtrr/main.c
      </sect1>
      <sect1><title>PCI Support Library</title>
 !Edrivers/pci/pci.c
+!Edrivers/pci/pci-driver.c
+!Edrivers/pci/remove.c
+!Edrivers/pci/pci-acpi.c
+<!-- kerneldoc does not understand to __devinit
+X!Edrivers/pci/search.c
+ -->
+!Edrivers/pci/msi.c
+!Edrivers/pci/bus.c
+!Edrivers/pci/hotplug.c
+!Edrivers/pci/probe.c
+!Edrivers/pci/rom.c
      </sect1>
      <sect1><title>PCI Hotplug Support Library</title>
 !Edrivers/pci/hotplug/pci_hotplug_core.c
@@ -223,6 +313,14 @@
 !Efs/devfs/base.c
   </chapter>
 
+  <chapter id="sysfs">
+     <title>The Filesystem for Exporting Kernel Objects</title>
+!Efs/sysfs/file.c
+!Efs/sysfs/dir.c
+!Efs/sysfs/symlink.c
+!Efs/sysfs/bin.c
+  </chapter>
+
   <chapter id="security">
      <title>Security Framework</title>
 !Esecurity/security.c
@@ -233,6 +331,61 @@
 !Ekernel/power/pm.c
   </chapter>
 
+  <chapter id="devdrivers">
+     <title>Device drivers infrastructure</title>
+     <sect1><title>Device Drivers Base</title>
+<!--
+X!Iinclude/linux/device.h
+-->
+!Edrivers/base/driver.c
+!Edrivers/base/class_simple.c
+!Edrivers/base/core.c
+!Edrivers/base/firmware_class.c
+!Edrivers/base/transport_class.c
+!Edrivers/base/dmapool.c
+<!-- Cannot be included, because
+     attribute_container_add_class_device_adapter
+ and attribute_container_classdev_to_container
+     exceed allowed 44 characters maximum
+X!Edrivers/base/attribute_container.c
+-->
+!Edrivers/base/sys.c
+<!--
+X!Edrivers/base/interface.c
+-->
+!Edrivers/base/platform.c
+!Edrivers/base/bus.c
+     </sect1>
+     <sect1><title>Device Drivers Power Management</title>
+!Edrivers/base/power/main.c
+!Edrivers/base/power/resume.c
+!Edrivers/base/power/suspend.c
+     </sect1>
+     <sect1><title>Device Drivers ACPI Support</title>
+<!-- Internal functions only
+X!Edrivers/acpi/sleep/main.c
+X!Edrivers/acpi/sleep/wakeup.c
+X!Edrivers/acpi/motherboard.c
+X!Edrivers/acpi/bus.c
+-->
+!Edrivers/acpi/scan.c
+<!-- No correct structured comments
+X!Edrivers/acpi/pci_bind.c
+-->
+     </sect1>
+     <sect1><title>Device drivers PnP support</title>
+!Edrivers/pnp/core.c
+<!-- No correct structured comments
+X!Edrivers/pnp/system.c
+ -->
+!Edrivers/pnp/card.c
+!Edrivers/pnp/driver.c
+!Edrivers/pnp/manager.c
+!Edrivers/pnp/support.c
+     </sect1>
+  </chapter>
+
+
   <chapter id="blkdev">
      <title>Block Devices</title>
 !Edrivers/block/ll_rw_blk.c
@@ -250,7 +403,23 @@
 
   <chapter id="snddev">
      <title>Sound Devices</title>
+!Iinclude/sound/core.h
 !Esound/sound_core.c
+!Iinclude/sound/pcm.h
+!Esound/core/pcm.c
+!Esound/core/device.c
+!Esound/core/info.c
+!Esound/core/rawmidi.c
+!Esound/core/sound.c
+!Esound/core/memory.c
+!Esound/core/pcm_memory.c
+!Esound/core/init.c
+!Esound/core/isadma.c
+!Esound/core/control.c
+!Esound/core/pcm_lib.c
+!Esound/core/hwdep.c
+!Esound/core/pcm_native.c
+!Esound/core/memalloc.c
 <!-- FIXME: Removed for now since no structured comments in source
 X!Isound/sound_firmware.c
 -->
@@ -258,6 +427,7 @@
 
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
+!Iinclude/linux/serial_core.h
 !Edrivers/serial/serial_core.c
 !Edrivers/serial/8250.c
   </chapter>
@@ -310,9 +480,11 @@
      <sect1><title>Frame Buffer Memory</title>
 !Edrivers/video/fbmem.c
      </sect1>
+<!--
      <sect1><title>Frame Buffer Console</title>
-!Edrivers/video/console/fbcon.c
+X!Edrivers/video/console/fbcon.c
      </sect1>
+-->
      <sect1><title>Frame Buffer Colormap</title>
 !Edrivers/video/fbcmap.c
      </sect1>
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl
new file mode 100644
index 0000000..e14c21d
--- /dev/null
+++ b/Documentation/DocBook/stylesheet.xsl
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<param name="chunk.quietly">1</param>
+<param name="funcsynopsis.style">ansi</param>
+</stylesheet>
diff --git a/Documentation/DocBook/tulip-user.tmpl b/Documentation/DocBook/tulip-user.tmpl
deleted file mode 100644
index 6520d7a..0000000
--- a/Documentation/DocBook/tulip-user.tmpl
+++ /dev/null
@@ -1,327 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="TulipUserGuide">
- <bookinfo>
-  <title>Tulip Driver User's Guide</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Jeff</firstname>
-    <surname>Garzik</surname>
-    <affiliation>
-     <address>
-      <email>jgarzik@pobox.com</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>2001</year>
-   <holder>Jeff Garzik</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License as published by the Free Software Foundation; either
-     version 2 of the License, or (at your option) any later
-     version.
-   </para>
-      
-   <para>
-     This program is distributed in the hope that it will be
-     useful, but WITHOUT ANY WARRANTY; without even the implied
-     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-     See the GNU General Public License for more details.
-   </para>
-      
-   <para>
-     You should have received a copy of the GNU General Public
-     License along with this program; if not, write to the Free
-     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-     MA 02111-1307 USA
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
- <toc></toc>
-
-  <chapter id="intro">
-    <title>Introduction</title>
-<para>
-The Tulip Ethernet Card Driver
-is maintained by Jeff Garzik (<email>jgarzik@pobox.com</email>).
-</para>
-
-<para>
-The Tulip driver was developed by Donald Becker and changed by
-Jeff Garzik, Takashi Manabe and a cast of thousands.
-</para>
-
-<para>
-For 2.4.x and later kernels, the Linux Tulip driver is available at
-<ulink url="http://sourceforge.net/projects/tulip/">http://sourceforge.net/projects/tulip/</ulink>
-</para>
-
-<para>
-	This driver is for the Digital "Tulip" Ethernet adapter interface.
-	It should work with most DEC 21*4*-based chips/ethercards, as well as
-	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
-</para>
-
-<para>
-        The original author may be reached as becker@scyld.com, or C/O
-        Scyld Computing Corporation,
-        410 Severn Ave., Suite 210,
-        Annapolis MD 21403
-</para>
-
-<para>
-	Additional information on Donald Becker's tulip.c
-	is available at <ulink url="http://www.scyld.com/network/tulip.html">http://www.scyld.com/network/tulip.html</ulink>
-</para>
-
-  </chapter>
-
-  <chapter id="drvr-compat">
-    <title>Driver Compatibility</title>
-
-<para>
-This device driver is designed for the DECchip "Tulip", Digital's
-single-chip ethernet controllers for PCI (now owned by Intel).
-Supported members of the family
-are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
-chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
-supported.
-</para>
-
-<para>
-These chips are used on at least 140 unique PCI board designs.  The great
-number of chips and board designs supported is the reason for the
-driver size and complexity.  Almost of the increasing complexity is in the
-board configuration and media selection code.  There is very little
-increasing in the operational critical path length.
-</para>
-  </chapter>
-
-  <chapter id="board-settings">
-    <title>Board-specific Settings</title>
-
-<para>
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS preferably should assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-</para>
-
-<para>
-Some boards have EEPROMs tables with default media entry.  The factory default
-is usually "autoselect".  This should only be overridden when using
-transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
-for forcing full-duplex when used with old link partners that do not do
-autonegotiation.
-</para>
-  </chapter>
-
-  <chapter id="driver-operation">
-    <title>Driver Operation</title>
-
-<sect1><title>Ring buffers</title>
-
-<para>
-The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
-This driver uses statically allocated rings of Rx and Tx descriptors, set at
-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
-for the Rx ring buffers at open() time and passes the skb->data field to the
-Tulip as receive data buffers.  When an incoming frame is less than
-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
-passed directly up the protocol stack and replaced by a newly allocated
-skbuff.
-</para>
-
-<para>
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames.  For small frames the copying cost is negligible (esp. considering
-that we are pre-loading the cache with immediately useful header
-information).  For large frames the copying cost is non-trivial, and the
-larger copy might flush the cache of useful data.  A subtle aspect of this
-choice is that the Tulip only receives into longword aligned buffers, thus
-the IP header at offset 14 isn't longword aligned for further processing.
-Copied frames are put into the new skbuff at an offset of "+2", thus copying
-has the beneficial effect of aligning the IP header and preloading the
-cache.
-</para>
-
-</sect1>
-
-<sect1><title>Synchronization</title>
-<para>
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-</para>
-
-<para>
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'tp->tx_full' flag.
-</para>
-
-<para>
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-</para>
-
-</sect1>
-
-  </chapter>
-
-  <chapter id="errata">
-    <title>Errata</title>
-
-<para>
-The old DEC databooks were light on details.
-The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
-register of the set CSR12-15 written.  Hmmm, now how is that possible?
-</para>
-
-<para>
-The DEC SROM format is very badly designed not precisely defined, leading to
-part of the media selection junkheap below.  Some boards do not have EEPROM
-media tables and need to be patched up.  Worse, other boards use the DEC
-design kit media table when it isn't correct for their board.
-</para>
-
-<para>
-We cannot use MII interrupts because there is no defined GPIO pin to attach
-them.  The MII transceiver status is polled using an kernel timer.
-</para>
-  </chapter>
-
-  <chapter id="changelog">
-    <title>Driver Change History</title>
-
-    <sect1><title>Version 0.9.14 (February 20, 2001)</title>
-    <itemizedlist>
-    <listitem><para>Fix PNIC problems (Manfred Spraul)</para></listitem>
-    <listitem><para>Add new PCI id for Accton comet</para></listitem>
-    <listitem><para>Support Davicom tulips</para></listitem>
-    <listitem><para>Fix oops in eeprom parsing</para></listitem>
-    <listitem><para>Enable workarounds for early PCI chipsets</para></listitem>
-    <listitem><para>IA64, hppa csr0 support</para></listitem>
-    <listitem><para>Support media types 5, 6</para></listitem>
-    <listitem><para>Interpret a bit more of the 21142 SROM extended media type 3</para></listitem>
-    <listitem><para>Add missing delay in eeprom reading</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.11 (November 3, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Eliminate extra bus accesses when sharing interrupts (prumpf)</para></listitem>
-    <listitem><para>Barrier following ownership descriptor bit flip (prumpf)</para></listitem>
-    <listitem><para>Endianness fixes for >14 addresses in setup frames (prumpf)</para></listitem>
-    <listitem><para>Report link beat to kernel/userspace via netif_carrier_*. (kuznet)</para></listitem>
-    <listitem><para>Better spinlocking in set_rx_mode.</para></listitem>
-    <listitem><para>Fix I/O resource request failure error messages (DaveM catch)</para></listitem>
-    <listitem><para>Handle DMA allocation failure.</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.10 (September 6, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Simple interrupt mitigation (via jamal)</para></listitem>
-    <listitem><para>More PCI ids</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.9 (August 11, 2000)</title>
-    <itemizedlist>
-    <listitem><para>More PCI ids</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.8 (July 13, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Correct signed/unsigned comparison for dummy frame index</para></listitem>
-    <listitem><para>Remove outdated references to struct enet_statistics</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.7 (June 17, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Timer cleanups (Andrew Morton)</para></listitem>
-    <listitem><para>Alpha compile fix (somebody?)</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.6 (May 31, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Revert 21143-related support flag patch</para></listitem>
-    <listitem><para>Add HPPA/media-table debugging printk</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.5 (May 30, 2000)</title>
-    <itemizedlist>
-    <listitem><para>HPPA support (willy@puffingroup)</para></listitem>
-    <listitem><para>CSR6 bits and tulip.h cleanup (Chris Smith)</para></listitem>
-    <listitem><para>Improve debugging messages a bit</para></listitem>
-    <listitem><para>Add delay after CSR13 write in t21142_start_nway</para></listitem>
-    <listitem><para>Remove unused ETHER_STATS code</para></listitem>
-    <listitem><para>Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith)</para></listitem>
-    <listitem><para>Update DS21143 support flags in tulip_chip_info[]</para></listitem>
-    <listitem><para>Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit()</para></listitem>
-    <listitem><para>Add locking to set_rx_mode()</para></listitem>
-    <listitem><para>Fix race with chip setting DescOwned bit (Hal Murray)</para></listitem>
-    <listitem><para>Request 100% of PIO and MMIO resource space assigned to card</para></listitem>
-    <listitem><para>Remove error message from pci_enable_device failure</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.4.3 (April 14, 2000)</title>
-    <itemizedlist>
-    <listitem><para>mod_timer fix (Hal Murray)</para></listitem>
-    <listitem><para>PNIC2 resuscitation (Chris Smith)</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.4.2 (March 21, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Fix 21041 CSR7, CSR13/14/15 handling</para></listitem>
-    <listitem><para>Merge some PCI ids from tulip 0.91x</para></listitem>
-    <listitem><para>Merge some HAS_xxx flags and flag settings from tulip 0.91x</para></listitem>
-    <listitem><para>asm/io.h fix (submitted by many) and cleanup</para></listitem>
-    <listitem><para>s/HAS_NWAY143/HAS_NWAY/</para></listitem>
-    <listitem><para>Cleanup 21041 mode reporting</para></listitem>
-    <listitem><para>Small code cleanups</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.4.1 (March 18, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Finish PCI DMA conversion (davem)</para></listitem>
-    <listitem><para>Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet)</para></listitem>
-    <listitem><para>PCI DMA fix (kuznet)</para></listitem>
-    <listitem><para>eeprom.c code cleanup</para></listitem>
-    <listitem><para>Remove Xircom Tulip crud</para></listitem>
-    </itemizedlist>
-    </sect1>
-  </chapter>
-
-</book>
diff --git a/Documentation/DocBook/via-audio.tmpl b/Documentation/DocBook/via-audio.tmpl
deleted file mode 100644
index 36e6421..0000000
--- a/Documentation/DocBook/via-audio.tmpl
+++ /dev/null
@@ -1,597 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="ViaAudioGuide">
- <bookinfo>
-  <title>Via 686 Audio Driver for Linux</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Jeff</firstname>
-    <surname>Garzik</surname>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>1999-2001</year>
-   <holder>Jeff Garzik</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License as published by the Free Software Foundation; either
-     version 2 of the License, or (at your option) any later
-     version.
-   </para>
-      
-   <para>
-     This program is distributed in the hope that it will be
-     useful, but WITHOUT ANY WARRANTY; without even the implied
-     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-     See the GNU General Public License for more details.
-   </para>
-      
-   <para>
-     You should have received a copy of the GNU General Public
-     License along with this program; if not, write to the Free
-     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-     MA 02111-1307 USA
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
-  <chapter id="intro">
-      <title>Introduction</title>
-  <para>
-  	The Via VT82C686A "super southbridge" chips contain
-	AC97-compatible audio logic which features dual 16-bit stereo
-	PCM sound channels (full duplex), plus a third PCM channel intended for use
-	in hardware-assisted FM synthesis.
-  </para>
-  <para>
-  	The current Linux kernel audio driver for this family of chips
-	supports audio playback and recording, but hardware-assisted
-	FM features, and hardware buffer direct-access (mmap)
-	support are not yet available.
-  </para>
-  <para>
-  	This driver supports any Linux kernel version after 2.4.10.
-  </para>
-  <para>
-	Please send bug reports to the mailing list <email>linux-via@gtf.org</email>.
-	To subscribe, e-mail <email>majordomo@gtf.org</email> with
-  </para>
-  <programlisting>
-	subscribe linux-via
-  </programlisting>
-  <para>
-	in the body of the message.
-  </para>
-  </chapter>
-  
-  <chapter id="install">
-      <title>Driver Installation</title>
-  <para>
-  	To use this audio driver, select the
-	CONFIG_SOUND_VIA82CXXX option in the section Sound during kernel configuration.
-	Follow the usual kernel procedures for rebuilding the kernel,
-	or building and installing driver modules.
-  </para>
-  <para>
-  	To make this driver the default audio driver, you can add the
-	following to your /etc/conf.modules file:
-  </para>
-  <programlisting>
-	alias sound via82cxxx_audio
-  </programlisting>
-  <para>
-  	Note that soundcore and ac97_codec support modules
-	are also required for working audio, in addition to
-	the via82cxxx_audio module itself.
-  </para>
-  </chapter>
-  
-  <chapter id="reportbug">
-      <title>Submitting a bug report</title>
-  <sect1 id="bugrepdesc"><title>Description of problem</title>
-  <para>
-	Describe the application you were using to play/record sound, and how
-	to reproduce the problem.
-  </para>
-  </sect1>
-  <sect1 id="bugrepdiag"><title>Diagnostic output</title>
-  <para>
-	Obtain the via-audio-diag diagnostics program from
-	http://sf.net/projects/gkernel/ and provide a dump of the
-	audio chip's registers while the problem is occurring.  Sample command line:
-  </para>
-  <programlisting>
-	./via-audio-diag -aps > diag-output.txt
-  </programlisting>
-  </sect1>
-  <sect1 id="bugrepdebug"><title>Driver debug output</title>
-  <para>
-	Define <constant>VIA_DEBUG</constant> at the beginning of the driver, then capture and email
-	the kernel log output.  This can be viewed in the system kernel log (if
-	enabled), or via the dmesg program.  Sample command line:
-  </para>
-  <programlisting>
-	dmesg > /tmp/dmesg-output.txt
-  </programlisting>
-  </sect1>
-  <sect1 id="bugrepprintk"><title>Bigger kernel message buffer</title>
-  <para>
-	If you wish to increase the size of the buffer displayed by dmesg, then
-	change the <constant>LOG_BUF_LEN</constant> macro at the top of linux/kernel/printk.c, recompile
-	your kernel, and pass the <constant>LOG_BUF_LEN</constant> value to dmesg.  Sample command line with
-	<constant>LOG_BUF_LEN</constant> == 32768:
-  </para>
-  <programlisting>
-	dmesg -s 32768 > /tmp/dmesg-output.txt
-  </programlisting>
-  </sect1>
-  </chapter>
-  
-  <chapter id="bugs">
-     <title>Known Bugs And Assumptions</title>
-  <para>
-  <variablelist>
-    <varlistentry><term>Low volume</term>
-    <listitem>
-    <para>
-	Volume too low on many systems.  Workaround:  use mixer program
-	such as xmixer to increase volume.
-    </para>
-    </listitem></varlistentry>
-
-  </variablelist>
-	
-  </para>
-  </chapter>
-
-  <chapter id="thanks">
-      <title>Thanks</title>
-  <para>
-	Via for providing e-mail support, specs, and NDA'd source code.
-  </para>
-  <para>
-	MandrakeSoft for providing hacking time.
-  </para>
-  <para>
-	AC97 mixer interface fixes and debugging by Ron Cemer <email>roncemer@gte.net</email>.
-  </para>
-  <para>
-	Rui Sousa <email>rui.sousa@conexant.com</email>, for bugfixing
-	MMAP support, and several other notable fixes that resulted from
-	his hard work and testing.
-  </para>
-  <para>
-	Adrian Cox <email>adrian@humboldt.co.uk</email>, for bugfixing
-	MMAP support, and several other notable fixes that resulted from
-	his hard work and testing.
-  </para>
-  <para>
-  	Thomas Sailer for further bugfixes.
-  </para>
-  </chapter>
-  
-  <chapter id="notes">
-     <title>Random Notes</title>
-  <para>
-	Two /proc pseudo-files provide diagnostic information.  This is generally
-	not useful to most users.  Power users can disable CONFIG_SOUND_VIA82CXXX_PROCFS,
-	and remove the /proc support code.  Once
-	version 2.0.0 is released, the /proc support code will be disabled by
-	default.  Available /proc pseudo-files:
-  </para>
-  <programlisting>
-	/proc/driver/via/0/info
-	/proc/driver/via/0/ac97
-  </programlisting>
-  <para>
-	This driver by default supports all PCI audio devices which report
-	a vendor id of 0x1106, and a device id of 0x3058.  Subsystem vendor
-	and device ids are not examined.
-  </para>
-  <para>
-	GNU indent formatting options:
-  <programlisting>
--kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl
-  </programlisting>
-  </para>
-  <para>
-	Via has graciously donated e-mail support and source code to help further
-	the development of this driver.  Their assistance has been invaluable
-	in the design and coding of the next major version of this driver.
-  </para>
-  <para>
-	The Via audio chip apparently provides a second PCM scatter-gather
-	DMA channel just for FM data, but does not have a full hardware MIDI
-	processor.  I haven't put much thought towards a solution here, but it
-	might involve using SoftOSS midi wave table, or simply disabling MIDI
-	support altogether and using the FM PCM channel as a second (input? output?)
-  </para>
-  </chapter>
-
-  <chapter id="changelog">
-      <title>Driver ChangeLog</title>
-
-<sect1 id="version191"><title>
-Version 1.9.1
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    DSP read/write bugfixes from Thomas Sailer.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Add new PCI id for single-channel use of Via 8233.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Other bug fixes, tweaks, new ioctls.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1115"><title>
-Version 1.1.15
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Support for variable fragment size and variable fragment number (Rui
-    Sousa)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &amp;
-    write mode (Rui Sousa)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Mmaped sound is now fully functional. (Rui Sousa)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Make sure to enable PCI device before reading any of its PCI
-    config information. (fixes potential hotplug problems)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Clean up code a bit and add more internal function documentation.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    AC97 codec access fixes (Adrian Cox)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Big endian fixes (Adrian Cox)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    MIDI support (Adrian Cox)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Detect and report locked-rate AC97 codecs.  If your hardware only
-    supports 48Khz (locked rate), then your recording/playback software
-    must upsample or downsample accordingly.  The hardware cannot do it.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Use new pci_request_regions and pci_disable_device functions in
-    kernel 2.4.6.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1114"><title>
-Version 1.1.14
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Use VM_RESERVE when available, to eliminate unnecessary page faults.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1112"><title>
-Version 1.1.12
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    mmap bug fixes from Linus.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1111"><title>
-Version 1.1.11
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Many more bug fixes.  mmap enabled by default, but may still be buggy.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Uses new and spiffy method of mmap'ing the DMA buffer, based
-    on a suggestion from Linus.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1110"><title>
-Version 1.1.10
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Many bug fixes.  mmap enabled by default, but may still be buggy.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version119"><title>
-Version 1.1.9
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Redesign and rewrite audio playback implementation.  (faster and smaller, hopefully)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Implement recording and full duplex (DSP_CAP_DUPLEX) support.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Make procfs support optional.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Quick interrupt status check, to lessen overhead in interrupt
-    sharing situations.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Add mmap(2) support.  Disabled for now, it is still buggy and experimental.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Surround all syscalls with a semaphore for cheap and easy SMP protection.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Fix bug in channel shutdown (hardware channel reset) code.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Remove unnecessary spinlocks (better performance).
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Eliminate "unknown AFMT" message by using a different method
-    of selecting the best AFMT_xxx sound sample format for use.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Support for realtime hardware pointer position reporting
-    (DSP_CAP_REALTIME, SNDCTL_DSP_GETxPTR ioctls)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Support for capture/playback triggering
-    (DSP_CAP_TRIGGER, SNDCTL_DSP_SETTRIGGER ioctls)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    SNDCTL_DSP_SETDUPLEX and SNDCTL_DSP_POST ioctls now handled.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Rewrite open(2) and close(2) logic to allow only one user at
-    a time.  All other open(2) attempts will sleep until they succeed.
-    FIXME: open(O_RDONLY) and open(O_WRONLY) should be allowed to succeed.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Reviewed code to ensure that SMP and multiple audio devices
-    are fully supported.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version118"><title>
-Version 1.1.8
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    	Clean up interrupt handler output.  Fixes the following kernel error message:
-    </para>
-  	<programlisting>
-	unhandled interrupt ...
-  	</programlisting>
-   </listitem>
-
-   <listitem>
-    <para>
-    	Convert documentation to DocBook, so that PDF, HTML and PostScript (.ps) output is readily
-	available.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version117"><title>
-Version 1.1.7
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Fix module unload bug where mixer device left registered
-  after driver exit
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version116"><title>
-Version 1.1.6
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Rewrite via_set_rate to mimic ALSA basic AC97 rate setting
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Remove much dead code
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Fix build problem in via_dsp_ioctl
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Optimize included headers to eliminate headers found in linux/sound
-	</para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version115"><title>
-Version 1.1.5
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Disable some overly-verbose debugging code
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Remove unnecessary sound locks
-   </para>
-   </listitem>
-   <listitem>
-    <para>
- Fix some ioctls for better time resolution
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version114"><title>
-Version 1.1.4
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Completed rewrite of driver.  Eliminated SoundBlaster compatibility
-  completely, and now uses the much-faster scatter-gather DMA engine.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-  </chapter>
-  
-  <chapter id="intfunctions">
-     <title>Internal Functions</title>
-!Isound/oss/via82cxxx_audio.c
-  </chapter>
-
-</book>
-
-
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 12250b3..9c6d450 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -108,8 +108,9 @@
 2004 has seen a Linux-Journal article on use of RCU in dcache
 [McKenney04a], a performance comparison of locking to RCU on several
 different CPUs [McKenney04b], a dissertation describing use of RCU in a
-number of operating-system kernels [PaulEdwardMcKenneyPhD], and a paper
-describing how to make RCU safe for soft-realtime applications [Sarma04c].
+number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper
+describing how to make RCU safe for soft-realtime applications [Sarma04c],
+and a paper describing SELinux performance with RCU [JamesMorris04b].
 
 
 Bibtex Entries
@@ -341,6 +342,17 @@
 ,pages="18-26"
 }
 
+@techreport{Friedberg03a
+,author="Stuart A. Friedberg"
+,title="Lock-Free Wild Card Search Data Structure and Method"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2003"
+,number="US Patent 6,662,184 (contributed under GPL)"
+,month="December"
+,pages="112"
+}
+
 @article{McKenney04a
 ,author="Paul E. McKenney and Dipankar Sarma and Maneesh Soni"
 ,title="Scaling dcache with {RCU}"
@@ -373,6 +385,9 @@
 ,school="OGI School of Science and Engineering at
 Oregon Health and Sciences University"
 ,year="2004"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/RCUdissertation.2004.07.14e1.pdf}
+[Viewed October 15, 2004]"
 }
 
 @Conference{Sarma04c
@@ -385,3 +400,13 @@
 ,month="June"
 ,pages="182-191"
 }
+
+@unpublished{JamesMorris04b
+,Author="James Morris"
+,Title="Recent Developments in {SELinux} Kernel Performance"
+,month="December"
+,year="2004"
+,note="Available:
+\url{http://www.livejournal.com/users/james_morris/2153.html}
+[Viewed December 10, 2004]"
+}
diff --git a/Documentation/RCU/UP.txt b/Documentation/RCU/UP.txt
index 551a803..3bfb84b 100644
--- a/Documentation/RCU/UP.txt
+++ b/Documentation/RCU/UP.txt
@@ -2,11 +2,11 @@
 
 
 A common misconception is that, on UP systems, the call_rcu() primitive
-may immediately invoke its function, and that the synchronize_kernel
+may immediately invoke its function, and that the synchronize_rcu()
 primitive may return immediately.  The basis of this misconception
 is that since there is only one CPU, it should not be necessary to
 wait for anything else to get done, since there are no other CPUs for
-anything else to be happening on.  Although this approach will sort of
+anything else to be happening on.  Although this approach will -sort- -of-
 work a surprising amount of the time, it is a very bad idea in general.
 This document presents two examples that demonstrate exactly how bad an
 idea this is.
@@ -44,14 +44,14 @@
 underlying RCU, namely that call_rcu() defers invoking its arguments until
 all RCU read-side critical sections currently executing have completed.
 
-Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in
+Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in
 this case?
 
 
 Summary
 
 Permitting call_rcu() to immediately invoke its arguments or permitting
-synchronize_kernel() to immediately return breaks RCU, even on a UP system.
+synchronize_rcu() to immediately return breaks RCU, even on a UP system.
 So do not do it!  Even on a UP system, the RCU infrastructure -must-
 respect grace periods.
 
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index b3a568a..8f3fb77 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -32,7 +32,10 @@
 	them -- even x86 allows reads to be reordered), and be prepared
 	to explain why this added complexity is worthwhile.  If you
 	choose #c, be prepared to explain how this single task does not
-	become a major bottleneck on big multiprocessor machines.
+	become a major bottleneck on big multiprocessor machines (for
+	example, if the task is updating information relating to itself
+	that other tasks can read, there by definition can be no
+	bottleneck).
 
 2.	Do the RCU read-side critical sections make proper use of
 	rcu_read_lock() and friends?  These primitives are needed
@@ -89,27 +92,34 @@
 		"_rcu()" list-traversal primitives, such as the
 		list_for_each_entry_rcu().
 
-	b.	If the list macros are being used, the list_del_rcu(),
-		list_add_tail_rcu(), and list_del_rcu() primitives must
-		be used in order to prevent weakly ordered machines from
-		misordering structure initialization and pointer planting.
+	b.	If the list macros are being used, the list_add_tail_rcu()
+		and list_add_rcu() primitives must be used in order
+		to prevent weakly ordered machines from misordering
+		structure initialization and pointer planting.
 		Similarly, if the hlist macros are being used, the
-		hlist_del_rcu() and hlist_add_head_rcu() primitives
-		are required.
+		hlist_add_head_rcu() primitive is required.
 
-	c.	Updates must ensure that initialization of a given
+	c.	If the list macros are being used, the list_del_rcu()
+		primitive must be used to keep list_del()'s pointer
+		poisoning from inflicting toxic effects on concurrent
+		readers.  Similarly, if the hlist macros are being used,
+		the hlist_del_rcu() primitive is required.
+
+		The list_replace_rcu() primitive may be used to
+		replace an old structure with a new one in an
+		RCU-protected list.
+
+	d.	Updates must ensure that initialization of a given
 		structure happens before pointers to that structure are
 		publicized.  Use the rcu_assign_pointer() primitive
 		when publicizing a pointer to a structure that can
 		be traversed by an RCU read-side critical section.
 
-		[The rcu_assign_pointer() primitive is in process.]
-
 5.	If call_rcu(), or a related primitive such as call_rcu_bh(),
 	is used, the callback function must be written to be called
 	from softirq context.  In particular, it cannot block.
 
-6.	Since synchronize_kernel() blocks, it cannot be called from
+6.	Since synchronize_rcu() can block, it cannot be called from
 	any sort of irq context.
 
 7.	If the updater uses call_rcu(), then the corresponding readers
@@ -125,9 +135,9 @@
 	such cases is a must, of course!  And the jury is still out on
 	whether the increased speed is worth it.
 
-8.	Although synchronize_kernel() is a bit slower than is call_rcu(),
+8.	Although synchronize_rcu() is a bit slower than is call_rcu(),
 	it usually results in simpler code.  So, unless update performance
-	is important or the updaters cannot block, synchronize_kernel()
+	is important or the updaters cannot block, synchronize_rcu()
 	should be used in preference to call_rcu().
 
 9.	All RCU list-traversal primitives, which include
@@ -155,3 +165,14 @@
 	you -must- use the "_rcu()" variants of the list macros.
 	Failing to do so will break Alpha and confuse people reading
 	your code.
+
+11.	Note that synchronize_rcu() -only- guarantees to wait until
+	all currently executing rcu_read_lock()-protected RCU read-side
+	critical sections complete.  It does -not- necessarily guarantee
+	that all currently running interrupts, NMIs, preempt_disable()
+	code, or idle loops will complete.  Therefore, if you do not have
+	rcu_read_lock()-protected read-side critical sections, do -not-
+	use synchronize_rcu().
+
+	If you want to wait for some of these other things, you might
+	instead need to use synchronize_irq() or synchronize_sched().
diff --git a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt
index bda6ead..f8a54fa 100644
--- a/Documentation/RCU/listRCU.txt
+++ b/Documentation/RCU/listRCU.txt
@@ -32,6 +32,7 @@
 		enum audit_state   state;
 
 		read_lock(&auditsc_lock);
+		/* Note: audit_netlink_sem held by caller. */
 		list_for_each_entry(e, &audit_tsklist, list) {
 			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
 				read_unlock(&auditsc_lock);
@@ -55,6 +56,7 @@
 		enum audit_state   state;
 
 		rcu_read_lock();
+		/* Note: audit_netlink_sem held by caller. */
 		list_for_each_entry_rcu(e, &audit_tsklist, list) {
 			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
 				rcu_read_unlock();
@@ -139,12 +141,15 @@
 a spin_lock() and a spin_unlock(), but in this case, all callers hold
 audit_netlink_sem, so no additional locking is required.  The auditsc_lock
 can therefore be eliminated, since use of RCU eliminates the need for
-writers to exclude readers.
+writers to exclude readers.  Normally, the write_lock() calls would
+be converted into spin_lock() calls.
 
 The list_del(), list_add(), and list_add_tail() primitives have been
 replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
 The _rcu() list-manipulation primitives add memory barriers that are
-needed on weakly ordered CPUs (most of them!).
+needed on weakly ordered CPUs (most of them!).  The list_del_rcu()
+primitive omits the pointer poisoning debug-assist code that would
+otherwise cause concurrent readers to fail spectacularly.
 
 So, when readers can tolerate stale data and when entries are either added
 or deleted, without in-place modification, it is very easy to use RCU!
@@ -166,6 +171,7 @@
 		struct audit_newentry *ne;
 
 		write_lock(&auditsc_lock);
+		/* Note: audit_netlink_sem held by caller. */
 		list_for_each_entry(e, list, list) {
 			if (!audit_compare_rule(rule, &e->rule)) {
 				e->rule.action = newaction;
@@ -199,8 +205,7 @@
 				audit_copy_rule(&ne->rule, &e->rule);
 				ne->rule.action = newaction;
 				ne->rule.file_count = newfield_count;
-				list_add_rcu(ne, e);
-				list_del(e);
+				list_replace_rcu(e, ne);
 				call_rcu(&e->rcu, audit_free_rule, e);
 				return 0;
 			}
diff --git a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt
index 7e0c2ab..eb44400 100644
--- a/Documentation/RCU/rcu.txt
+++ b/Documentation/RCU/rcu.txt
@@ -43,7 +43,9 @@
 
 o	How can I see where RCU is currently used in the Linux kernel?
 
-	Search for "rcu_read_lock", "call_rcu", and "synchronize_kernel".
+	Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu",
+	"rcu_read_lock_bh", "rcu_read_unlock_bh", "call_rcu_bh",
+	"synchronize_rcu", and "synchronize_net".
 
 o	What guidelines should I follow when writing code that uses RCU?
 
diff --git a/Documentation/aoe/aoe.txt b/Documentation/aoe/aoe.txt
index 43e5010..3a4dbe4 100644
--- a/Documentation/aoe/aoe.txt
+++ b/Documentation/aoe/aoe.txt
@@ -4,6 +4,16 @@
 
   It has many tips and hints!
 
+The aoetools are userland programs that are designed to work with this
+driver.  The aoetools are on sourceforge.
+
+  http://aoetools.sourceforge.net/
+
+The scripts in this Documentation/aoe directory are intended to
+document the use of the driver and are not necessary if you install
+the aoetools.
+
+
 CREATING DEVICE NODES
 
   Users of udev should find the block device nodes created
@@ -35,14 +45,15 @@
 
   "echo eth2 eth4 > /dev/etherd/interfaces" tells the aoe driver to
   limit ATA over Ethernet traffic to eth2 and eth4.  AoE traffic from
-  untrusted networks should be ignored as a matter of security.
+  untrusted networks should be ignored as a matter of security.  See
+  also the aoe_iflist driver option described below.
 
   "echo > /dev/etherd/discover" tells the driver to find out what AoE
   devices are available.
 
   These character devices may disappear and be replaced by sysfs
-  counterparts, so distribution maintainers are encouraged to create
-  scripts that use these devices.
+  counterparts.  Using the commands in aoetools insulates users from
+  these implementation details.
 
   The block devices are named like this:
 
@@ -66,7 +77,8 @@
   through which we are communicating with the remote AoE device.
 
   There is a script in this directory that formats this information
-  in a convenient way.
+  in a convenient way.  Users with aoetools can use the aoe-stat
+  command.
 
   root@makki root# sh Documentation/aoe/status.sh 
      e10.0            eth3              up
@@ -89,3 +101,23 @@
       e4.7            eth1              up
       e4.8            eth1              up
       e4.9            eth1              up
+
+  Use /sys/module/aoe/parameters/aoe_iflist (or better, the driver
+  option discussed below) instead of /dev/etherd/interfaces to limit
+  AoE traffic to the network interfaces in the given
+  whitespace-separated list.  Unlike the old character device, the
+  sysfs entry can be read from as well as written to.
+
+  It's helpful to trigger discovery after setting the list of allowed
+  interfaces.  The aoetools package provides an aoe-discover script
+  for this purpose.  You can also directly use the
+  /dev/etherd/discover special file described above.
+
+DRIVER OPTIONS
+
+  There is a boot option for the built-in aoe driver and a
+  corresponding module parameter, aoe_iflist.  Without this option,
+  all network interfaces may be used for ATA over Ethernet.  Here is a
+  usage example for the module parameter.
+
+    modprobe aoe_iflist="eth1 eth3"
diff --git a/Documentation/aoe/status.sh b/Documentation/aoe/status.sh
index 6628116..751f3be 100644
--- a/Documentation/aoe/status.sh
+++ b/Documentation/aoe/status.sh
@@ -14,10 +14,6 @@
 	echo "$me Error: sysfs is not mounted" 1>&2
 	exit 1
 }
-test -z "`lsmod | grep '^aoe'`" && {
-	echo  "$me Error: aoe module is not loaded" 1>&2
-	exit 1
-}
 
 for d in `ls -d $sysd/block/etherd* 2>/dev/null | grep -v p` end; do
 	# maybe ls comes up empty, so we use "end"
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 734fcc8..9a33bb9 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -1,137 +1,140 @@
-.*
-*~
-53c8xx_d.h*
 *.a
-aic7*reg.h*
-aic7*seq.h*
-aic7*reg_print.c*
+*.aux
+*.bin
+*.cpio
+*.css
+*.dvi
+*.eps
+*.gif
+*.grep
+*.grp
+*.gz
+*.html
+*.jpeg
+*.ko
+*.log
+*.lst
+*.mod.c
+*.o
+*.orig
+*.out
+*.pdf
+*.png
+*.ps
+*.rej
+*.s
+*.sgml
+*.so
+*.tex
+*.ver
+*.xml
+*_MODULES
+*_vga16.c
+*cscope*
+*~
+.*
+.cscope
 53c700_d.h
+53c8xx_d.h*
+BitKeeper
+COPYING
+CREDITS
+CVS
+ChangeSet
+Kerntypes
+MODS.txt
+Module.symvers
+PENDING
+SCCS
+System.map*
+TAGS
+aic7*reg.h*
+aic7*reg_print.c*
+aic7*seq.h*
 aicasm
 aicdb.h*
 asm
 asm_offsets.*
 autoconf.h*
-*.aux
 bbootsect
-*.bin
 bin2c
 binkernel.spec
-BitKeeper
 bootsect
 bsetup
 btfixupprep
 build
 bvmlinux
 bzImage*
-ChangeSet
 classlist.h*
-compile.h*
 comp*.log
+compile.h*
 config
 config-*
 config_data.h*
 conmakehash
 consolemap_deftbl.c*
-COPYING
-CREDITS
-.cscope
-*cscope*
+crc32table.h*
 cscope.*
-*.out
-*.css
-CVS
 defkeymap.c*
 devlist.h*
 docproc
 dummy_sym.c*
-*.dvi
-*.eps
+elfconfig.h*
 filelist
 fixdep
 fore200e_mkfirm
 fore200e_pca_fw.c*
 gen-devlist
-gen_init_cpio
-gen_crc32table
-crc32table.h*
-*.cpio
 gen-kdb_cmds.c*
-gentbl
+gen_crc32table
+gen_init_cpio
 genksyms
-*.gif
-*.gz
-*.html
+gentbl
 ikconfig.h*
 initramfs_list
-*.jpeg
+kallsyms
 kconfig
 kconfig.tk
-Kerntypes
 keywords.c*
 ksym.c*
 ksym.h*
-kallsyms
-mk_elfconfig
-elfconfig.h*
-modpost
-pnmtologo
-logo_*.c
-*.log
 lex.c*
+logo_*.c
 logo_*_clut224.c
 logo_*_mono.c
 lxdialog
 make_times_h
 map
-mkdep
-*_MODULES
-MODS.txt
-modversions.h*
-Module.symvers
-*.mod.c
-*.o
-*.ko
-*.orig
-*.lst
-*.grp
-*.grep
-oui.c*
-mktables
-raid6tables.c
-raid6int*.c
-raid6altivec*.c
-wanxlfw.inc
 maui_boot.h
-pss_boot.h
-trix_boot.h
-*.pdf
+mk_elfconfig
+mkdep
+mktables
+modpost
+modversions.h*
+offsets.h
+oui.c*
 parse.c*
 parse.h*
-PENDING
+pnmtologo
 ppc_defs.h*
 promcon_tbl.c*
-*.png
-*.ps
-*.rej
-SCCS
+pss_boot.h
+raid6altivec*.c
+raid6int*.c
+raid6tables.c
 setup
-*.s
-*.so
-*.sgml
 sim710_d.h*
 sm_tbl*
 split-include
-System.map*
 tags
-TAGS
-*.tex
 times.h*
 tkparse
-*.ver
+trix_boot.h
 version.h*
-*_vga16.c
 vmlinux
-vmlinux.lds
 vmlinux-*
+vmlinux.lds
 vsyscall.lds
+wanxlfw.inc
+uImage
 zImage
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 56627c1..d3c52dd 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -48,3 +48,18 @@
 Why:	Replaced by ->compat_ioctl in file_operations and other method
 	vecors.
 Who:	Andi Kleen <ak@muc.de>, Christoph Hellwig <hch@lst.de>
+
+---------------------------
+
+What:	RCU API moves to EXPORT_SYMBOL_GPL
+When:	April 2006
+Files:	include/linux/rcupdate.h, kernel/rcupdate.c
+Why:	Outside of Linux, the only implementations of anything even
+	vaguely resembling RCU that I am aware of are in DYNIX/ptx,
+	VM/XA, Tornado, and K42.  I do not expect anyone to port binary
+	drivers or kernel modules from any of these, since the first two
+	are owned by IBM and the last two are open-source research OSes.
+	So these will move to GPL after a grace period to allow
+	people, who might be using implementations that I am not aware
+	of, to adjust to this upcoming change.
+Who:	Paul E. McKenney <paulmck@us.ibm.com>
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index a934bae..1045da5 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -219,8 +219,12 @@
 If the filesytem is called for sync then it must wait on any
 in-progress I/O and then start new I/O.
 
-The filesystem should unlock the page synchronously, before returning
-to the caller.
+The filesystem should unlock the page synchronously, before returning to the
+caller, unless ->writepage() returns special WRITEPAGE_ACTIVATE
+value. WRITEPAGE_ACTIVATE means that page cannot really be written out
+currently, and VM should stop calling ->writepage() on this page for some
+time. VM does this by moving page to the head of the active list, hence the
+name.
 
 Unless the filesystem is going to redirty_page_for_writepage(), unlock the page
 and return zero, writepage *must* run set_page_writeback() against the page,
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index cbe85c1..6c98f2b 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -909,16 +909,6 @@
 Represents the  number of free inodes. Ie. The number of inuse inodes is
 (nr_inodes - nr_free_inodes).
 
-super-nr and super-max
-----------------------
-
-Again, super  block structures are allocated by the kernel, but not freed. The
-file super-max  contains  the  maximum  number  of super block handlers, where
-super-nr shows the number of currently allocated ones.
-
-Every mounted file system needs a super block, so if you plan to mount lots of
-file systems, you may want to increase these numbers.
-
 aio-nr and aio-max-nr
 ---------------------
 
diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
index 67c053a..df28c74 100644
--- a/Documentation/i386/zero-page.txt
+++ b/Documentation/i386/zero-page.txt
@@ -79,6 +79,6 @@
 0x22c   unsigned long	ramdisk_max
 0x230   16 bytes 	trampoline
 0x290 - 0x2cf		EDD_MBR_SIG_BUFFER (edd.S)
-0x2d0 - 0x600		E820MAP
-0x600 - 0x7ff		EDDBUF (edd.S) for disk signature read sector
-0x600 - 0x7eb		EDDBUF (edd.S) for edd data
+0x2d0 - 0xd00		E820MAP
+0xd00 - 0xeff		EDDBUF (edd.S) for disk signature read sector
+0xd00 - 0xeeb		EDDBUF (edd.S) for edd data
diff --git a/Documentation/networking/DLINK.txt b/Documentation/networking/DLINK.txt
index 083d247..55d2443 100644
--- a/Documentation/networking/DLINK.txt
+++ b/Documentation/networking/DLINK.txt
@@ -178,10 +178,9 @@
 	7. ACKNOWLEDGMENTS.
 
 	These drivers wouldn't have been done without the base
-	(and support) from Ross Biro <bir7@leland.stanford.edu>,
-	and D-Link Systems Inc.  The driver relies upon GPL-ed
-	source from D-Link Systems Inc. and from Russel Nelson at
-	Crynwr Software <nelson@crynwr.com>.
+	(and support) from Ross Biro, and D-Link Systems Inc.
+	The driver relies upon GPL-ed source from D-Link Systems Inc.
+	and from Russel Nelson at Crynwr Software <nelson@crynwr.com>.
 
 	Additional input also from:
 	Donald Becker <becker@super.org>, Alan Cox <A.Cox@swansea.ac.uk>
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 1509f3a..3c0a5ba 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -51,6 +51,8 @@
 	set_multicast_list
 	Context: BHs disabled
 	Notes: netif_queue_stopped() is guaranteed false
+               Interrupts must be enabled when calling hard_start_xmit.
+                (Interrupts must also be enabled when enabling the BH handler.)
 	Return codes: 
 	o NETDEV_TX_OK everything ok. 
 	o NETDEV_TX_BUSY Cannot transmit packet, try later 
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 67514bf..62b1dc5 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -279,6 +279,7 @@
 pci_for_each_bus()		Superseded by pci_find_next_bus()
 pci_find_device()		Superseded by pci_get_device()
 pci_find_subsys()		Superseded by pci_get_subsys()
+pci_find_slot()			Superseded by pci_get_slot()
 pcibios_find_class()		Superseded by pci_get_class()
 pci_find_class()		Superseded by pci_get_class()
 pci_(read|write)_*_nodev()	Superseded by pci_bus_(read|write)_*()
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index c85428e..35b1a7d 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -165,40 +165,9 @@
 These functions are intended for use by individual drivers, and are defined in 
 struct pci_driver:
 
-        int  (*save_state) (struct pci_dev *dev, u32 state);
-        int  (*suspend) (struct pci_dev *dev, u32 state);
+        int  (*suspend) (struct pci_dev *dev, pm_message_t state);
         int  (*resume) (struct pci_dev *dev);
-        int  (*enable_wake) (struct pci_dev *dev, u32 state, int enable);
-
-
-save_state
-----------
-
-Usage:
-
-if (dev->driver && dev->driver->save_state)
-	dev->driver->save_state(dev,state);
-
-The driver should use this callback to save device state. It should take into
-account the current state of the device and the requested state in order to
-avoid any unnecessary operations.
-
-For example, a video card that supports all 4 states (D0-D3), all controller
-context is preserved when entering D1, but the screen is placed into a low power
-state (blanked). 
-
-The driver can also interpret this function as a notification that it may be
-entering a sleep state in the near future. If it knows that the device cannot
-enter the requested state, either because of lack of support for it, or because
-the device is middle of some critical operation, then it should fail.
-
-This function should not be used to set any state in the device or the driver
-because the device may not actually enter the sleep state (e.g. another driver
-later causes causes a global state transition to fail).
-
-Note that in intermediate low power states, a device's I/O and memory spaces may
-be disabled and may not be available in subsequent transitions to lower power
-states.
+        int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);
 
 
 suspend
diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt
index d939717..f0be389 100644
--- a/Documentation/s390/cds.txt
+++ b/Documentation/s390/cds.txt
@@ -56,12 +56,16 @@
    read device characteristics
    
 read_conf_data()
+read_conf_data_lpm()
    read configuration data.
 
 ccw_device_get_ciw()
    get commands from extended sense data.
 
 ccw_device_start()	
+ccw_device_start_timeout()
+ccw_device_start_key()
+ccw_device_start_key_timeout()
    initiate an I/O request.
 
 ccw_device_resume()
@@ -197,19 +201,21 @@
           operational.
 
 
-read_conf_data() - Read Configuration Data
+read_conf_data(), read_conf_data_lpm() - Read Configuration Data
 
 Retrieve the device dependent configuration data. Please have a look at your 
 device dependent I/O commands for the device specific layout of the node 
-descriptor elements. 
+descriptor elements. read_conf_data_lpm() will retrieve the configuration data
+for a specific path.
 
-The function is meant to be called with an irq handler in place; that is,
+The function is meant to be called with the device already enabled; that is,
 at earliest during set_online() processing.
 
 The function may be called enabled or disabled, but the device must not be
 locked
 
-int read_conf_data(struct ccw_device, void **buffer, int *length, __u8 lpm);
+int read_conf_data(struct ccw_device, void **buffer, int *length);
+int read_conf_data_lpm(struct ccw_device, void **buffer, int *length, __u8 lpm);
 
 cdev   - the ccw_device the data is requested for.
 buffer - Pointer to a buffer pointer. The read_conf_data() routine
@@ -263,6 +269,25 @@
 		     unsigned long intparm,
 		     __u8 lpm,
 		     unsigned long flags);
+int ccw_device_start_timeout(struct ccw_device *cdev,
+			     struct ccw1 *cpa,
+			     unsigned long intparm,
+			     __u8 lpm,
+			     unsigned long flags,
+			     int expires);
+int ccw_device_start_key(struct ccw_device *cdev,
+			 struct ccw1 *cpa,
+			 unsigned long intparm,
+			 __u8 lpm,
+			 __u8 key,
+			 unsigned long flags);
+int ccw_device_start_key_timeout(struct ccw_device *cdev,
+				 struct ccw1 *cpa,
+				 unsigned long intparm,
+				 __u8 lpm,
+				 __u8 key,
+				 unsigned long flags,
+				 int expires);
 
 cdev         : ccw_device the I/O is destined for
 cpa          : logical start address of channel program
@@ -272,7 +297,12 @@
                particular I/O request.
 lpm          : defines the channel path to be used for a specific I/O
                request. A value of 0 will make cio use the opm.
+key	     : the storage key to use for the I/O (useful for operating on a
+	       storage with a storage key != default key)
 flag         : defines the action to be performed for I/O processing
+expires      : timeout value in jiffies. The common I/O layer will terminate
+	       the running program after this and call the interrupt handler
+	       with ERR_PTR(-ETIMEDOUT) as irb.
 
 Possible flag values are :
 
@@ -327,6 +357,13 @@
 interrupt will be presented to indicate I/O completion as the I/O request was
 never started, even though ccw_device_start() returned with successful completion.
 
+The irb may contain an error value, and the device driver should check for this
+first:
+
+-ETIMEDOUT: the common I/O layer terminated the request after the specified
+            timeout value
+-EIO:       the common I/O layer terminated the request due to an error state
+
 If the concurrent sense flag in the extended status word in the irb is set, the
 field irb->scsw.count describes the numer of device specific sense bytes
 available in the extended control word irb->scsw.ecw[0]. No device sensing by
diff --git a/MAINTAINERS b/MAINTAINERS
index 4333b69..5b84833 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1699,7 +1699,9 @@
 M:	proski@gnu.org
 P:	David Gibson
 M:	hermes@gibson.dropbear.id.au
-W:	http://www.ozlabs.org/people/dgibson/dldwd
+L:	orinoco-users@lists.sourceforge.net
+L:	orinoco-devel@lists.sourceforge.net
+W:	http://www.nongnu.org/orinoco/
 S:	Maintained
 
 PARALLEL PORT SUPPORT
@@ -2113,6 +2115,13 @@
 L:	alsa-devel@alsa-project.org
 S:	Maintained
 
+TPM DEVICE DRIVER
+P:	Kylene Hall
+M:	kjhall@us.ibm.com
+W:	http://tpmdd.sourceforge.net
+L:	tpmdd-devel@lists.sourceforge.net
+S:	Maintained
+
 UltraSPARC (sparc64):
 P:	David S. Miller
 M:	davem@davemloft.net
diff --git a/Makefile b/Makefile
index 8da3a30..bddcb86 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION =-rc3
+EXTRAVERSION =-rc4
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
@@ -332,9 +332,7 @@
 PERL		= perl
 CHECK		= sparse
 
-NOSTDINC_FLAGS  = -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
-CHECKFLAGS     += $(NOSTDINC_FLAGS)
 MODFLAGS	= -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -531,6 +529,10 @@
 
 include $(srctree)/arch/$(ARCH)/Makefile
 
+# arch Makefile may override CC so keep this after arch Makefile is included
+NOSTDINC_FLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+CHECKFLAGS     += $(NOSTDINC_FLAGS)
+
 # warn about C99 declaration after statement
 CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 
@@ -1188,8 +1190,8 @@
 quiet_cmd_tags = MAKE   $@
 define cmd_tags
 	rm -f $@; \
-	CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL"`; \
-	$(all-sources) | xargs ctags $$CTAGSF -a --extra=+f
+	CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
+	$(all-sources) | xargs ctags $$CTAGSF -a
 endef
 
 TAGS: FORCE
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 0c79b9d..f7c9663 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -280,6 +280,10 @@
 	  (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
 	  newer boards don't support it.  If you have ISA, say Y, otherwise N.
 
+config ISA_DMA_API
+	bool
+	default y
+
 config PCI
 	bool
 	depends on !ALPHA_JENSEN
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index b5d0fd2..64e450d 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -457,22 +457,6 @@
 	return 0;
 }
 
-asmlinkage long
-osf_shmat(int shmid, void __user *shmaddr, int shmflg)
-{
-	unsigned long raddr;
-	long err;
-
-	err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-
-	/*
-	 * This works because all user-level addresses are
-	 * non-negative longs!
-	 */
-	return err ? err : (long)raddr;
-}
-
-
 /*
  * The following stuff should move into a header file should it ever
  * be labeled "officially supported."  Right now, there is just enough
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index d005831..bbd3753 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -14,6 +14,7 @@
 #include <linux/user.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -335,7 +336,7 @@
 		/* continue and stop at next (return from) syscall */
 	case PTRACE_CONT:    /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -365,7 +366,7 @@
 
 	case PTRACE_SINGLESTEP:  /* execute single instruction. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		/* Mark single stepping.  */
 		child->thread_info->bpt_nsaved = -1;
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 3864b33..0521208 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -227,7 +227,7 @@
 	.quad sys_semop
 	.quad osf_utsname
 	.quad sys_lchown
-	.quad osf_shmat
+	.quad sys_shmat
 	.quad sys_shmctl			/* 210 */
 	.quad sys_shmdt
 	.quad sys_shmget
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4055115..bf397a9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -85,6 +85,7 @@
 config ARCH_CLPS7500
 	bool "Cirrus-CL-PS7500FE"
 	select TIMER_ACORN
+	select ISA
 
 config ARCH_CLPS711X
 	bool "CLPS711x/EP721x-based"
@@ -96,6 +97,7 @@
 
 config ARCH_EBSA110
 	bool "EBSA-110"
+	select ISA
 	help
 	  This is an evaluation board for the StrongARM processor available
 	  from Digital. It has limited hardware on-board, including an onboard
@@ -120,13 +122,16 @@
 
 config ARCH_IOP3XX
 	bool "IOP3xx-based"
+	select PCI
 
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 	select DMABOUNCE
+	select PCI
 
 config ARCH_IXP2000
 	bool "IXP2400/2800-based"
+	select PCI
 
 config ARCH_L7200
 	bool "LinkUp-L7200"
@@ -155,6 +160,8 @@
 
 config ARCH_SA1100
 	bool "SA1100-based"
+	select ISA
+	select DISCONTIGMEM
 
 config ARCH_S3C2410
 	bool "Samsung S3C2410"
@@ -165,6 +172,9 @@
 
 config ARCH_SHARK
 	bool "Shark"
+	select ISA
+	select ISA_DMA
+	select PCI
 
 config ARCH_LH7A40X
 	bool "Sharp LH7A40X"
@@ -252,8 +262,6 @@
 
 config ISA
 	bool
-	depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
-	default y
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
 	  name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -263,12 +271,13 @@
 
 config ISA_DMA
 	bool
-	depends on FOOTBRIDGE_HOST || ARCH_SHARK
+
+config ISA_DMA_API
+	bool
 	default y
 
 config PCI
 	bool "PCI support" if ARCH_INTEGRATOR_AP
-	default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -296,7 +305,7 @@
 
 config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && n
+	depends on EXPERIMENTAL #&& n
 	help
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
@@ -336,8 +345,7 @@
 
 config DISCONTIGMEM
 	bool
-	depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
-	default y
+	default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
 	help
 	  Say Y to support efficient handling of discontiguous physical memory,
 	  for architectures which are either NUMA (Non-Uniform Memory Access)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index c0e7aff..7c7f475 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -18,48 +18,30 @@
  * Please select one of the following when turning on debugging.
  */
 #ifdef DEBUG
-#if defined(CONFIG_DEBUG_DC21285_PORT)
-		.macro	loadsp, rb
-		mov	\rb, #0x42000000
-		.endm
-		.macro	writeb, rb
-		str	\rb, [r3, #0x160]
-		.endm
-#elif defined(CONFIG_DEBUG_ICEDCC)
+
+#include <asm/arch/debug-macro.S>
+
+#if defined(CONFIG_DEBUG_ICEDCC)
 		.macro	loadsp, rb
 		.endm
-		.macro writeb, rb
-		mcr	p14, 0, \rb, c0, c1, 0
+		.macro writeb, ch, rb
+		mcr	p14, 0, \ch, c0, c1, 0
 		.endm
-#elif defined(CONFIG_FOOTBRIDGE)
+#else
+		.macro	writeb,	ch, rb
+		senduart \ch, \rb
+		.endm
+
+#if defined(CONFIG_FOOTBRIDGE) || \
+    defined(CONFIG_ARCH_RPC) || \
+    defined(CONFIG_ARCH_INTEGRATOR) || \
+    defined(CONFIG_ARCH_PXA) || \
+    defined(CONFIG_ARCH_IXP4XX) || \
+    defined(CONFIG_ARCH_IXP2000) || \
+    defined(CONFIG_ARCH_LH7A40X) || \
+    defined(CONFIG_ARCH_OMAP)
 		.macro	loadsp,	rb
-		mov	\rb, #0x7c000000
-		.endm
-		.macro	writeb,	rb
-		strb	\rb, [r3, #0x3f8]
-		.endm
-#elif defined(CONFIG_ARCH_RPC)
-		.macro	loadsp,	rb
-		mov	\rb, #0x03000000
-		orr	\rb, \rb, #0x00010000
-		.endm
-		.macro	writeb,	rb
-		strb	\rb, [r3, #0x3f8 << 2]
-		.endm
-#elif defined(CONFIG_ARCH_INTEGRATOR)
-		.macro	loadsp, rb
-		mov	\rb, #0x16000000
-		.endm
-		.macro	writeb, rb
-		strb	\rb, [r3, #0]
-		.endm
-#elif defined(CONFIG_ARCH_PXA) /* Xscale-type */
-		.macro 	loadsp, rb
-		mov	\rb, #0x40000000
-		orr	\rb, \rb, #0x00100000
-		.endm
-		.macro	writeb, rb
-		strb	\rb, [r3, #0]
+		addruart \rb
 		.endm
 #elif defined(CONFIG_ARCH_SA1100)
 		.macro	loadsp, rb
@@ -70,65 +52,22 @@
 		add	\rb, \rb, #0x00010000	@ Ser1
 #  endif
 		.endm
-		.macro	writeb, rb
-		str	\rb, [r3, #0x14]	@ UTDR
-		.endm
-#elif defined(CONFIG_ARCH_IXP4XX)
-		.macro	loadsp, rb
-		mov	\rb, #0xc8000000
-		.endm
-		.macro	writeb, rb
-		str	\rb, [r3, #0]
-#elif defined(CONFIG_ARCH_IXP2000)
-		.macro	loadsp, rb
-		mov	\rb, #0xc0000000
-		orr	\rb, \rb, #0x00030000
-		.endm
-		.macro	writeb, rb
-		str	\rb, [r3, #0]
-		.endm
-#elif defined(CONFIG_ARCH_LH7A40X)
-		.macro	loadsp, rb
-		ldr	\rb, =0x80000700	@ UART2 UARTBASE
-		.endm
-		.macro	writeb, rb
-		strb	\rb, [r3, #0]
-		.endm
-#elif defined(CONFIG_ARCH_OMAP)
-		.macro  loadsp, rb
-		mov	\rb, #0xff000000	@ physical base address
-		add	\rb, \rb, #0x00fb0000
-#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3)
-		add	\rb, \rb, #0x00000800
-#endif
-#ifdef CONFIG_OMAP_LL_DEBUG_UART3
-		add	\rb, \rb, #0x00009000
-#endif
-		.endm
-		.macro	writeb, rb
-		strb	\rb, [r3]
-		.endm
 #elif defined(CONFIG_ARCH_IOP331)
 		.macro loadsp, rb
                 mov   	\rb, #0xff000000
                 orr     \rb, \rb, #0x00ff0000
                 orr     \rb, \rb, #0x0000f700   @ location of the UART
 		.endm
-		.macro	writeb, rb
-		str	\rb, [r3, #0]
-		.endm
 #elif defined(CONFIG_ARCH_S3C2410)
-			.macro loadsp, rb
+		.macro loadsp, rb
 		mov	\rb, #0x50000000
 		add	\rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT
 		.endm
-		.macro	writeb, rb
-		strb	\rb, [r3, #0x20]
-		.endm
 #else
 #error no serial architecture defined
 #endif
 #endif
+#endif
 
 		.macro	kputc,val
 		mov	r0, \val
@@ -734,7 +673,7 @@
 1:		ldrb	r2, [r0], #1
 		teq	r2, #0
 		moveq	pc, lr
-2:		writeb	r2
+2:		writeb	r2, r3
 		mov	r1, #0x00020000
 3:		subs	r1, r1, #1
 		bne	3b
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index c397e71..72b03f2 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -141,10 +141,10 @@
 	next->tm_sec = alrm->tm_sec;
 }
 
-static inline void rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
+static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
 {
 	memset(tm, 0, sizeof(struct rtc_time));
-	ops->read_time(tm);
+	return ops->read_time(tm);
 }
 
 static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
@@ -163,8 +163,7 @@
 	int ret = -EINVAL;
 	if (ops->read_alarm) {
 		memset(alrm, 0, sizeof(struct rtc_wkalrm));
-		ops->read_alarm(alrm);
-		ret = 0;
+		ret = ops->read_alarm(alrm);
 	}
 	return ret;
 }
@@ -283,7 +282,9 @@
 		break;
 
 	case RTC_RD_TIME:
-		rtc_read_time(ops, &tm);
+		ret = rtc_read_time(ops, &tm);
+		if (ret)
+			break;
 		ret = copy_to_user(uarg, &tm, sizeof(tm));
 		if (ret)
 			ret = -EFAULT;
@@ -424,15 +425,15 @@
 	struct rtc_time tm;
 	char *p = page;
 
-	rtc_read_time(ops, &tm);
-
-	p += sprintf(p,
-		"rtc_time\t: %02d:%02d:%02d\n"
-		"rtc_date\t: %04d-%02d-%02d\n"
-		"rtc_epoch\t: %04lu\n",
-		tm.tm_hour, tm.tm_min, tm.tm_sec,
-		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-		rtc_epoch);
+	if (rtc_read_time(ops, &tm) == 0) {
+		p += sprintf(p,
+			"rtc_time\t: %02d:%02d:%02d\n"
+			"rtc_date\t: %04d-%02d-%02d\n"
+			"rtc_epoch\t: %04lu\n",
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+			rtc_epoch);
+	}
 
 	if (rtc_read_alarm(ops, &alrm) == 0) {
 		p += sprintf(p, "alrm_time\t: ");
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index d36f991..7be3521 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -133,7 +133,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0"
 # CONFIG_XIP_KERNEL is not set
 
 #
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 07a56ff..4a2af55 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -31,8 +31,3 @@
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 
 extra-y := $(head-y) init_task.o vmlinux.lds
-
-# Spell out some dependencies that aren't automatically figured out
-$(obj)/entry-armv.o: 	$(obj)/entry-header.S include/asm-arm/constants.h
-$(obj)/entry-common.o: 	$(obj)/entry-header.S include/asm-arm/constants.h \
-			$(obj)/calls.S
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 99d4325..c1ff4d1 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -64,6 +64,26 @@
   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
   DEFINE(TI_IWMMXT_STATE,	(offsetof(struct thread_info, fpstate)+4)&~7);
   BLANK();
+  DEFINE(S_R0,			offsetof(struct pt_regs, ARM_r0));
+  DEFINE(S_R1,			offsetof(struct pt_regs, ARM_r1));
+  DEFINE(S_R2,			offsetof(struct pt_regs, ARM_r2));
+  DEFINE(S_R3,			offsetof(struct pt_regs, ARM_r3));
+  DEFINE(S_R4,			offsetof(struct pt_regs, ARM_r4));
+  DEFINE(S_R5,			offsetof(struct pt_regs, ARM_r5));
+  DEFINE(S_R6,			offsetof(struct pt_regs, ARM_r6));
+  DEFINE(S_R7,			offsetof(struct pt_regs, ARM_r7));
+  DEFINE(S_R8,			offsetof(struct pt_regs, ARM_r8));
+  DEFINE(S_R9,			offsetof(struct pt_regs, ARM_r9));
+  DEFINE(S_R10,			offsetof(struct pt_regs, ARM_r10));
+  DEFINE(S_FP,			offsetof(struct pt_regs, ARM_fp));
+  DEFINE(S_IP,			offsetof(struct pt_regs, ARM_ip));
+  DEFINE(S_SP,			offsetof(struct pt_regs, ARM_sp));
+  DEFINE(S_LR,			offsetof(struct pt_regs, ARM_lr));
+  DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
+  DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
+  DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
+  DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
+  BLANK();
 #if __LINUX_ARM_ARCH__ >= 6
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
   BLANK();
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index bb27c31..4eb3615 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -14,12 +14,12 @@
  *  it to save wrong values...  Be aware!
  */
 #include <linux/config.h>
-#include <linux/init.h>
 
-#include <asm/thread_info.h>
 #include <asm/glue.h>
-#include <asm/ptrace.h>
 #include <asm/vfpmacros.h>
+#include <asm/hardware.h>		/* should be moved into entry-macro.S */
+#include <asm/arch/irqs.h>		/* should be moved into entry-macro.S */
+#include <asm/arch/entry-macro.S>
 
 #include "entry-header.S"
 
@@ -118,7 +118,7 @@
 	@
 	@ IRQs off again before pulling preserved data off the stack
 	@
-	disable_irq r0
+	disable_irq
 
 	@
 	@ restore SPSR and restart the instruction
@@ -198,7 +198,7 @@
 	@
 	@ IRQs off again before pulling preserved data off the stack
 	@
-1:	disable_irq r0
+1:	disable_irq
 
 	@
 	@ restore SPSR and restart the instruction
@@ -232,7 +232,7 @@
 	@
 	@ IRQs off again before pulling preserved data off the stack
 	@
-	disable_irq r0
+	disable_irq
 
 	@
 	@ restore SPSR and restart the instruction
@@ -269,6 +269,12 @@
 	add	r5, sp, #S_PC
 	ldmia	r7, {r2 - r4}			@ Get USR pc, cpsr
 
+#if __LINUX_ARM_ARCH__ < 6
+	@ make sure our user space atomic helper is aborted
+	cmp	r2, #VIRT_OFFSET
+	bichs	r3, r3, #PSR_Z_BIT
+#endif
+
 	@
 	@ We are now ready to fill in the remaining blanks on the stack:
 	@
@@ -316,7 +322,7 @@
 	@
 	@ IRQs on, then call the main handler
 	@
-	enable_irq r2
+	enable_irq
 	mov	r2, sp
 	adr	lr, ret_from_exception
 	b	do_DataAbort
@@ -418,7 +424,7 @@
 	movcss	r7, r5, lsr #(TIF_USING_IWMMXT + 1)
 	bcs	iwmmxt_task_enable
 #endif
-	enable_irq r7
+	enable_irq
 	add	pc, pc, r8, lsr #6
 	mov	r0, r0
 
@@ -472,7 +478,7 @@
 __pabt_usr:
 	usr_entry abt
 
-	enable_irq r0				@ Enable interrupts
+	enable_irq				@ Enable interrupts
 	mov	r0, r2				@ address (pc)
 	mov	r1, sp				@ regs
 	bl	do_PrefetchAbort		@ call abort handler
@@ -499,8 +505,12 @@
 	mra	r4, r5, acc0
 	stmia   ip, {r4, r5}
 #endif
+#if defined(CONFIG_HAS_TLS_REG)
+	mcr	p15, 0, r3, c13, c0, 3		@ set TLS register
+#elif !defined(CONFIG_TLS_REG_EMUL)
 	mov	r4, #0xffff0fff
-	str	r3, [r4, #-3]			@ Set TLS ptr
+	str	r3, [r4, #-15]			@ TLS val at 0xffff0ff0
+#endif
 	mcr	p15, 0, r6, c3, c0, 0		@ Set domain register
 #ifdef CONFIG_VFP
 	@ Always disable VFP so we can lazily save/restore the old
@@ -519,11 +529,209 @@
 	ldmib	r2, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
 
 	__INIT
+
+/*
+ * User helpers.
+ *
+ * These are segment of kernel provided user code reachable from user space
+ * at a fixed address in kernel memory.  This is used to provide user space
+ * with some operations which require kernel help because of unimplemented
+ * native feature and/or instructions in many ARM CPUs. The idea is for
+ * this code to be executed directly in user mode for best efficiency but
+ * which is too intimate with the kernel counter part to be left to user
+ * libraries.  In fact this code might even differ from one CPU to another
+ * depending on the available  instruction set and restrictions like on
+ * SMP systems.  In other words, the kernel reserves the right to change
+ * this code as needed without warning. Only the entry points and their
+ * results are guaranteed to be stable.
+ *
+ * Each segment is 32-byte aligned and will be moved to the top of the high
+ * vector page.  New segments (if ever needed) must be added in front of
+ * existing ones.  This mechanism should be used only for things that are
+ * really small and justified, and not be abused freely.
+ *
+ * User space is expected to implement those things inline when optimizing
+ * for a processor that has the necessary native support, but only if such
+ * resulting binaries are already to be incompatible with earlier ARM
+ * processors due to the use of unsupported instructions other than what
+ * is provided here.  In other words don't make binaries unable to run on
+ * earlier processors just for the sake of not using these kernel helpers
+ * if your compiled code is not going to use the new instructions for other
+ * purpose.
+ */
+
+	.align	5
+	.globl	__kuser_helper_start
+__kuser_helper_start:
+
+/*
+ * Reference prototype:
+ *
+ *	int __kernel_cmpxchg(int oldval, int newval, int *ptr)
+ *
+ * Input:
+ *
+ *	r0 = oldval
+ *	r1 = newval
+ *	r2 = ptr
+ *	lr = return address
+ *
+ * Output:
+ *
+ *	r0 = returned value (zero or non-zero)
+ *	C flag = set if r0 == 0, clear if r0 != 0
+ *
+ * Clobbered:
+ *
+ *	r3, ip, flags
+ *
+ * Definition and user space usage example:
+ *
+ *	typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
+ *	#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
+ *
+ * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
+ * Return zero if *ptr was changed or non-zero if no exchange happened.
+ * The C flag is also set if *ptr was changed to allow for assembly
+ * optimization in the calling code.
+ *
+ * For example, a user space atomic_add implementation could look like this:
+ *
+ * #define atomic_add(ptr, val) \
+ *	({ register unsigned int *__ptr asm("r2") = (ptr); \
+ *	   register unsigned int __result asm("r1"); \
+ *	   asm volatile ( \
+ *	       "1: @ atomic_add\n\t" \
+ *	       "ldr	r0, [r2]\n\t" \
+ *	       "mov	r3, #0xffff0fff\n\t" \
+ *	       "add	lr, pc, #4\n\t" \
+ *	       "add	r1, r0, %2\n\t" \
+ *	       "add	pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
+ *	       "bcc	1b" \
+ *	       : "=&r" (__result) \
+ *	       : "r" (__ptr), "rIL" (val) \
+ *	       : "r0","r3","ip","lr","cc","memory" ); \
+ *	   __result; })
+ */
+
+__kuser_cmpxchg:				@ 0xffff0fc0
+
+#if __LINUX_ARM_ARCH__ < 6
+
+#ifdef CONFIG_SMP  /* sanity check */
+#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?"
+#endif
+
+	/*
+	 * Theory of operation:
+	 *
+	 * We set the Z flag before loading oldval. If ever an exception
+	 * occurs we can not be sure the loaded value will still be the same
+	 * when the exception returns, therefore the user exception handler
+	 * will clear the Z flag whenever the interrupted user code was
+	 * actually from the kernel address space (see the usr_entry macro).
+	 *
+	 * The post-increment on the str is used to prevent a race with an
+	 * exception happening just after the str instruction which would
+	 * clear the Z flag although the exchange was done.
+	 */
+	teq	ip, ip			@ set Z flag
+	ldr	ip, [r2]		@ load current val
+	add	r3, r2, #1		@ prepare store ptr
+	teqeq	ip, r0			@ compare with oldval if still allowed
+	streq	r1, [r3, #-1]!		@ store newval if still allowed
+	subs	r0, r2, r3		@ if r2 == r3 the str occured
+	mov	pc, lr
+
+#else
+
+	ldrex	r3, [r2]
+	subs	r3, r3, r0
+	strexeq	r3, r1, [r2]
+	rsbs	r0, r3, #0
+	mov	pc, lr
+
+#endif
+
+	.align	5
+
+/*
+ * Reference prototype:
+ *
+ *	int __kernel_get_tls(void)
+ *
+ * Input:
+ *
+ *	lr = return address
+ *
+ * Output:
+ *
+ *	r0 = TLS value
+ *
+ * Clobbered:
+ *
+ *	the Z flag might be lost
+ *
+ * Definition and user space usage example:
+ *
+ *	typedef int (__kernel_get_tls_t)(void);
+ *	#define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0)
+ *
+ * Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
+ *
+ * This could be used as follows:
+ *
+ * #define __kernel_get_tls() \
+ *	({ register unsigned int __val asm("r0"); \
+ *         asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \
+ *	        : "=r" (__val) : : "lr","cc" ); \
+ *	   __val; })
+ */
+
+__kuser_get_tls:				@ 0xffff0fe0
+
+#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
+
+	ldr	r0, [pc, #(16 - 8)]		@ TLS stored at 0xffff0ff0
+	mov	pc, lr
+
+#else
+
+	mrc	p15, 0, r0, c13, c0, 3		@ read TLS register
+	mov	pc, lr
+
+#endif
+
+	.rep	5
+	.word	0			@ pad up to __kuser_helper_version
+	.endr
+
+/*
+ * Reference declaration:
+ *
+ *	extern unsigned int __kernel_helper_version;
+ *
+ * Definition and user space usage example:
+ *
+ *	#define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
+ *
+ * User space may read this to determine the curent number of helpers
+ * available.
+ */
+
+__kuser_helper_version:				@ 0xffff0ffc
+	.word	((__kuser_helper_end - __kuser_helper_start) >> 5)
+
+	.globl	__kuser_helper_end
+__kuser_helper_end:
+
+
 /*
  * Vector stubs.
  *
- * This code is copied to 0x200 or 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's.
+ * This code is copied to 0xffff0200 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not
+ * exceed 0x300 bytes.
  *
  * Common stub entry macro:
  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
@@ -544,7 +752,7 @@
 	@
 	mrs	r13, cpsr
 	bic	r13, r13, #MODE_MASK
-	orr	r13, r13, #MODE_SVC
+	orr	r13, r13, #SVC_MODE
 	msr	spsr_cxsf, r13			@ switch to SVC_32 mode
 
 	and	lr, lr, #15
@@ -552,6 +760,7 @@
 	movs	pc, lr				@ Changes mode and branches
 	.endm
 
+	.globl	__stubs_start
 __stubs_start:
 /*
  * Interrupt dispatcher
@@ -686,37 +895,24 @@
 .LCsabt:
 	.word	__temp_abt
 
+	.globl	__stubs_end
 __stubs_end:
 
-	.equ	__real_stubs_start, .LCvectors + 0x200
+	.equ	stubs_offset, __vectors_start + 0x200 - __stubs_start
 
-.LCvectors:
+	.globl	__vectors_start
+__vectors_start:
 	swi	SYS_ERROR0
-	b	__real_stubs_start + (vector_und - __stubs_start)
-	ldr	pc, __real_stubs_start + (.LCvswi - __stubs_start)
-	b	__real_stubs_start + (vector_pabt - __stubs_start)
-	b	__real_stubs_start + (vector_dabt - __stubs_start)
-	b	__real_stubs_start + (vector_addrexcptn - __stubs_start)
-	b	__real_stubs_start + (vector_irq - __stubs_start)
-	b	__real_stubs_start + (vector_fiq - __stubs_start)
+	b	vector_und + stubs_offset
+	ldr	pc, .LCvswi + stubs_offset
+	b	vector_pabt + stubs_offset
+	b	vector_dabt + stubs_offset
+	b	vector_addrexcptn + stubs_offset
+	b	vector_irq + stubs_offset
+	b	vector_fiq + stubs_offset
 
-ENTRY(__trap_init)
-	stmfd	sp!, {r4 - r6, lr}
-
-	mov	r0, #0xff000000
-	orr	r0, r0, #0x00ff0000		@ high vectors position
-	adr	r1, .LCvectors			@ set up the vectors
-	ldmia	r1, {r1, r2, r3, r4, r5, r6, ip, lr}
-	stmia	r0, {r1, r2, r3, r4, r5, r6, ip, lr}
-
-	add	r2, r0, #0x200
-	adr	r0, __stubs_start		@ copy stubs to 0x200
-	adr	r1, __stubs_end
-1:	ldr	r3, [r0], #4
-	str	r3, [r2], #4
-	cmp	r0, r1
-	blt	1b
-	LOADREGS(fd, sp!, {r4 - r6, pc})
+	.globl	__vectors_end
+__vectors_end:
 
 	.data
 
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 53a7e0d..3f8d0e3 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -9,19 +9,10 @@
  */
 #include <linux/config.h>
 
-#include <asm/thread_info.h>
-#include <asm/ptrace.h>
 #include <asm/unistd.h>
 
 #include "entry-header.S"
 
-/* 
- * We rely on the fact that R0 is at the bottom of the stack (due to
- * slow/fast restore user regs).
- */
-#if S_R0 != 0
-#error "Please fix"
-#endif
 
 	.align	5
 /*
@@ -30,11 +21,19 @@
  * stack.
  */
 ret_fast_syscall:
-	disable_irq r1				@ disable interrupts
+	disable_irq				@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
 	bne	fast_work_pending
-	fast_restore_user_regs
+
+	@ fast_restore_user_regs
+	ldr	r1, [sp, #S_OFF + S_PSR]	@ get calling cpsr
+	ldr	lr, [sp, #S_OFF + S_PC]!	@ get pc
+	msr	spsr_cxsf, r1			@ save in spsr_svc
+	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
+	mov	r0, r0
+	add	sp, sp, #S_FRAME_SIZE - S_PC
+	movs	pc, lr				@ return & move spsr_svc into cpsr
 
 /*
  * Ok, we need to do extra processing, enter the slow path.
@@ -49,7 +48,7 @@
 	mov	r0, sp				@ 'regs'
 	mov	r2, why				@ 'syscall'
 	bl	do_notify_resume
-	disable_irq r1				@ disable interrupts
+	disable_irq				@ disable interrupts
 	b	no_work_pending
 
 work_resched:
@@ -59,12 +58,19 @@
  */
 ENTRY(ret_to_user)
 ret_slow_syscall:
-	disable_irq r1				@ disable interrupts
+	disable_irq				@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
 	bne	work_pending
 no_work_pending:
-	slow_restore_user_regs
+	@ slow_restore_user_regs
+	ldr	r1, [sp, #S_PSR]		@ get calling cpsr
+	ldr	lr, [sp, #S_PC]!		@ get pc
+	msr	spsr_cxsf, r1			@ save in spsr_svc
+	ldmdb	sp, {r0 - lr}^			@ get calling r1 - lr
+	mov	r0, r0
+	add	sp, sp, #S_FRAME_SIZE - S_PC
+	movs	pc, lr				@ return & move spsr_svc into cpsr
 
 /*
  * This is how we return from a fork.
@@ -116,9 +122,26 @@
 
 	.align	5
 ENTRY(vector_swi)
-	save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0 - r12
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^			@ Calling sp, lr
+	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
+	str	lr, [sp, #S_PC]			@ Save calling PC
+	str	r8, [sp, #S_PSR]		@ Save CPSR
+	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
 	zero_fp
-	get_scno
+
+	/*
+	 * Get the system call number.
+	 */
+#ifdef CONFIG_ARM_THUMB
+	tst	r8, #PSR_T_BIT			@ this is SPSR from save_user_regs
+	addne	scno, r7, #__NR_SYSCALL_BASE	@ put OS number in
+	ldreq	scno, [lr, #-4]
+#else
+	ldr	scno, [lr, #-4]			@ get SWI instruction
+#endif
 	arm710_bug_check scno, ip
 
 #ifdef CONFIG_ALIGNMENT_TRAP
@@ -126,14 +149,14 @@
 	ldr	ip, [ip]
 	mcr	p15, 0, ip, c1, c0		@ update control register
 #endif
-	enable_irq ip
+	enable_irq
 
 	str	r4, [sp, #-S_OFF]!		@ push fifth arg
 
 	get_thread_info tsk
 	ldr	ip, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	bic	scno, scno, #0xff000000		@ mask off SWI op-code
-	eor	scno, scno, #OS_NUMBER << 20	@ check OS number
+	eor	scno, scno, #__NR_SYSCALL_BASE	@ check OS number
 	adr	tbl, sys_call_table		@ load syscall table pointer
 	tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
 	bne	__sys_trace
@@ -144,8 +167,8 @@
 
 	add	r1, sp, #S_OFF
 2:	mov	why, #0				@ no longer a real syscall
-	cmp	scno, #ARMSWI_OFFSET
-	eor	r0, scno, #OS_NUMBER << 20	@ put OS number back
+	cmp	scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
+	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back
 	bcs	arm_syscall	
 	b	sys_ni_syscall			@ not private func
 
@@ -190,7 +213,7 @@
 @ r5 = syscall table
 		.type	sys_syscall, #function
 sys_syscall:
-		eor	scno, r0, #OS_NUMBER << 20
+		eor	scno, r0, #__NR_SYSCALL_BASE
 		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE
 		cmpne	scno, #NR_syscalls	@ check range
 		stmloia	sp, {r5, r6}		@ shuffle args
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 4039d8c..a3d40a0 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -1,24 +1,11 @@
-#include <linux/config.h> /* for CONFIG_ARCH_xxxx */
+#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
 #include <asm/constants.h>
 #include <asm/errno.h>
-#include <asm/hardware.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/entry-macro.S>
-
-#ifndef MODE_SVC
-#define MODE_SVC 0x13
-#endif
-
-	.macro	zero_fp
-#ifdef CONFIG_FRAME_POINTER
-	mov	fp, #0
-#endif
-	.endm
-
-	.text
+#include <asm/thread_info.h>
 
 @ Bad Abort numbers
 @ -----------------
@@ -29,113 +16,44 @@
 #define BAD_IRQ		3
 #define BAD_UNDEFINSTR	4
 
-#define PT_TRACESYS	0x00000002
-
-@ OS version number used in SWIs
-@  RISC OS is 0
-@  RISC iX is 8
 @
-#define OS_NUMBER	9
-#define ARMSWI_OFFSET	0x000f0000
-
+@ Most of the stack format comes from struct pt_regs, but with
+@ the addition of 8 bytes for storing syscall args 5 and 6.
 @
-@ Stack format (ensured by USER_* and SVC_*)
-@
-#define S_FRAME_SIZE	72
-#define S_OLD_R0	68
-#define S_PSR		64
-
-#define S_PC		60
-#define S_LR		56
-#define S_SP		52
-#define S_IP		48
-#define S_FP		44
-#define S_R10		40
-#define S_R9		36
-#define S_R8		32
-#define S_R7		28
-#define S_R6		24
-#define S_R5		20
-#define S_R4		16
-#define S_R3		12
-#define S_R2		8
-#define S_R1		4
-#define S_R0		0
 #define S_OFF		8
 
-	.macro	set_cpsr_c, reg, mode
-	msr	cpsr_c, \mode
+/* 
+ * The SWI code relies on the fact that R0 is at the bottom of the stack
+ * (due to slow/fast restore user regs).
+ */
+#if S_R0 != 0
+#error "Please fix"
+#endif
+
+	.macro	zero_fp
+#ifdef CONFIG_FRAME_POINTER
+	mov	fp, #0
+#endif
 	.endm
 
 #if __LINUX_ARM_ARCH__ >= 6
-	.macro	disable_irq, temp
+	.macro	disable_irq
 	cpsid	i
 	.endm
 
-	.macro	enable_irq, temp
+	.macro	enable_irq
 	cpsie	i
 	.endm
 #else
-	.macro	disable_irq, temp
-	set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC
+	.macro	disable_irq
+	msr	cpsr_c, #PSR_I_BIT | SVC_MODE
 	.endm
 
-	.macro	enable_irq, temp
-	set_cpsr_c \temp, #MODE_SVC
+	.macro	enable_irq
+	msr	cpsr_c, #SVC_MODE
 	.endm
 #endif
 
-	.macro	save_user_regs
-	sub	sp, sp, #S_FRAME_SIZE
-	stmia	sp, {r0 - r12}			@ Calling r0 - r12
-	add	r8, sp, #S_PC
-	stmdb	r8, {sp, lr}^			@ Calling sp, lr
-	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
-	str	lr, [sp, #S_PC]			@ Save calling PC
-	str	r8, [sp, #S_PSR]		@ Save CPSR
-	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
-	.endm
-
-	.macro	restore_user_regs
-	ldr	r1, [sp, #S_PSR]		@ Get calling cpsr
-	disable_irq ip				@ disable IRQs
-	ldr	lr, [sp, #S_PC]!		@ Get PC
-	msr	spsr_cxsf, r1			@ save in spsr_svc
-	ldmdb	sp, {r0 - lr}^			@ Get calling r0 - lr
-	mov	r0, r0
-	add	sp, sp, #S_FRAME_SIZE - S_PC
-	movs	pc, lr				@ return & move spsr_svc into cpsr
-	.endm
-
-/*
- * Must be called with IRQs already disabled.
- */
-	.macro	fast_restore_user_regs
-	ldr	r1, [sp, #S_OFF + S_PSR]	@ get calling cpsr
-	ldr	lr, [sp, #S_OFF + S_PC]!	@ get pc
-	msr	spsr_cxsf, r1			@ save in spsr_svc
-	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
-	mov	r0, r0
-	add	sp, sp, #S_FRAME_SIZE - S_PC
-	movs	pc, lr				@ return & move spsr_svc into cpsr
-	.endm
-
-/*
- * Must be called with IRQs already disabled.
- */
-	.macro	slow_restore_user_regs
-	ldr	r1, [sp, #S_PSR]		@ get calling cpsr
-	ldr	lr, [sp, #S_PC]!		@ get pc
-	msr	spsr_cxsf, r1			@ save in spsr_svc
-	ldmdb	sp, {r0 - lr}^			@ get calling r1 - lr
-	mov	r0, r0
-	add	sp, sp, #S_FRAME_SIZE - S_PC
-	movs	pc, lr				@ return & move spsr_svc into cpsr
-	.endm
-
-	.macro	mask_pc, rd, rm
-	.endm
-
 	.macro	get_thread_info, rd
 	mov	\rd, sp, lsr #13
 	mov	\rd, \rd, lsl #13
@@ -165,18 +83,3 @@
 tbl	.req	r8		@ syscall table pointer
 why	.req	r8		@ Linux syscall (!= 0)
 tsk	.req	r9		@ current thread_info
-
-/*
- * Get the system call number.
- */
-	.macro	get_scno
-#ifdef CONFIG_ARM_THUMB
-	tst	r8, #PSR_T_BIT		@ this is SPSR from save_user_regs
-	addne	scno, r7, #OS_NUMBER << 20 @ put OS number in
-	ldreq	scno, [lr, #-4]
-
-#else
-	mask_pc	lr, lr
-	ldr	scno, [lr, #-4]		@ get SWI instruction
-#endif
-	.endm
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 171b3e8..4733877 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -19,6 +19,7 @@
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/constants.h>
+#include <asm/thread_info.h>
 #include <asm/system.h>
 
 #define PROCINFO_MMUFLAGS	8
@@ -131,7 +132,7 @@
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
 	.long	cr_alignment			@ r6
-	.long	init_thread_union+8192		@ sp
+	.long	init_thread_union + THREAD_START_SP @ sp
 
 /*
  * The following fragment of code is executed with the MMU on, and uses
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 26eacd3..8f146a4 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -256,8 +256,6 @@
 static unsigned int nr_thread_info;
 
 #define EXTRA_TASK_STRUCT	4
-#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
 
 struct thread_info *alloc_thread_info(struct task_struct *task)
 {
@@ -274,17 +272,16 @@
 	}
 
 	if (!thread)
-		thread = ll_alloc_task_struct();
+		thread = (struct thread_info *)
+			   __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
 
-#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_DEBUG_STACK_USAGE
 	/*
 	 * The stack must be cleared if you want SYSRQ-T to
 	 * give sensible stack usage information
 	 */
-	if (thread) {
-		char *p = (char *)thread;
-		memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
-	}
+	if (thread)
+		memzero(thread, THREAD_SIZE);
 #endif
 	return thread;
 }
@@ -297,7 +294,7 @@
 		thread_info_head = p;
 		nr_thread_info += 1;
 	} else
-		ll_free_task_struct(thread);
+		free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
 }
 
 /*
@@ -350,7 +347,7 @@
 	struct thread_info *thread = p->thread_info;
 	struct pt_regs *childregs;
 
-	childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1;
+	childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_START_SP)) - 1;
 	*childregs = *regs;
 	childregs->ARM_r0 = 0;
 	childregs->ARM_sp = stack_start;
@@ -447,15 +444,17 @@
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long fp, lr;
-	unsigned long stack_page;
+	unsigned long stack_start, stack_end;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
-	stack_page = 4096 + (unsigned long)p->thread_info;
+	stack_start = (unsigned long)(p->thread_info + 1);
+	stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE;
+
 	fp = thread_saved_fp(p);
 	do {
-		if (fp < stack_page || fp > 4092+stack_page)
+		if (fp < stack_start || fp > stack_end)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
 		if (!in_sched_functions(lr))
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index efd7a34..cd99b83 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -19,6 +19,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/init.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -693,7 +694,7 @@
 		case PTRACE_SYSCALL:
 		case PTRACE_CONT:
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			if (request == PTRACE_SYSCALL)
 				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -728,7 +729,7 @@
 		 */
 		case PTRACE_SINGLESTEP:
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			child->ptrace |= PT_SINGLESTEP;
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 7ba6342..f897ce2 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -227,18 +227,6 @@
 	}
 }
 
-asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg,
-			  unsigned long __user *addr)
-{
-	unsigned long ret;
-	long err;
-
-	err = do_shmat(shmid, shmaddr, shmflg, &ret);
-	if (err == 0)
-		err = put_user(ret, addr);
-	return err;
-}
-
 /* Fork a new task - this creates a new program thread.
  * This is called indirectly via a small wrapper
  */
@@ -314,7 +302,7 @@
 		"b	ret_to_user"
 		:
 		: "r" (current_thread_info()),
-		  "Ir" (THREAD_SIZE - 8 - sizeof(regs)),
+		  "Ir" (THREAD_START_SP - sizeof(regs)),
 		  "r" (&regs),
 		  "Ir" (sizeof(regs))
 		: "r0", "r1", "r2", "r3", "ip", "memory");
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6e31718..14df16b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -218,7 +218,8 @@
 		tsk->comm, tsk->pid, tsk->thread_info + 1);
 
 	if (!user_mode(regs) || in_interrupt()) {
-		dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info);
+		dump_mem("Stack: ", regs->ARM_sp,
+			 THREAD_SIZE + (unsigned long)tsk->thread_info);
 		dump_backtrace(regs, tsk);
 		dump_instr(regs);
 	}
@@ -450,13 +451,17 @@
 
 	case NR(set_tls):
 		thread->tp_value = regs->ARM_r0;
+#if defined(CONFIG_HAS_TLS_REG)
+		asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) );
+#elif !defined(CONFIG_TLS_REG_EMUL)
 		/*
-		 * Our user accessible TLS ptr is located at 0xffff0ffc.
-		 * On SMP read access to this address must raise a fault
-		 * and be emulated from the data abort handler.
-		 * m
+		 * User space must never try to access this directly.
+		 * Expect your app to break eventually if you do so.
+		 * The user helper at 0xffff0fe0 must be used instead.
+		 * (see entry-armv.S for details)
 		 */
-		*((unsigned long *)0xffff0ffc) = thread->tp_value;
+		*((unsigned int *)0xffff0ff0) = regs->ARM_r0;
+#endif
 		return 0;
 
 	default:
@@ -493,6 +498,44 @@
 	return 0;
 }
 
+#ifdef CONFIG_TLS_REG_EMUL
+
+/*
+ * We might be running on an ARMv6+ processor which should have the TLS
+ * register but for some reason we can't use it, or maybe an SMP system
+ * using a pre-ARMv6 processor (there are apparently a few prototypes like
+ * that in existence) and therefore access to that register must be
+ * emulated.
+ */
+
+static int get_tp_trap(struct pt_regs *regs, unsigned int instr)
+{
+	int reg = (instr >> 12) & 15;
+	if (reg == 15)
+		return 1;
+	regs->uregs[reg] = current_thread_info()->tp_value;
+	regs->ARM_pc += 4;
+	return 0;
+}
+
+static struct undef_hook arm_mrc_hook = {
+	.instr_mask	= 0x0fff0fff,
+	.instr_val	= 0x0e1d0f70,
+	.cpsr_mask	= PSR_T_BIT,
+	.cpsr_val	= 0,
+	.fn		= get_tp_trap,
+};
+
+static int __init arm_mrc_hook_init(void)
+{
+	register_undef_hook(&arm_mrc_hook);
+	return 0;
+}
+
+late_initcall(arm_mrc_hook_init);
+
+#endif
+
 void __bad_xchg(volatile void *ptr, int size)
 {
 	printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
@@ -578,9 +621,19 @@
 
 void __init trap_init(void)
 {
-	extern void __trap_init(void);
+	extern char __stubs_start[], __stubs_end[];
+	extern char __vectors_start[], __vectors_end[];
+	extern char __kuser_helper_start[], __kuser_helper_end[];
+	int kuser_sz = __kuser_helper_end - __kuser_helper_start;
 
-	__trap_init();
+	/*
+	 * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
+	 * into the vector page, mapped at 0xffff0000, and ensure these
+	 * are visible to the instruction stream.
+	 */
+	memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
+	memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
+	memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
 	flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a39c6a4..ad2d66c 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -5,6 +5,7 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <linux/config.h>
+#include <asm/thread_info.h>
 	
 OUTPUT_ARCH(arm)
 ENTRY(stext)
@@ -103,7 +104,7 @@
 	__data_loc = ALIGN(4);		/* location in binary */
 	. = DATAADDR;
 #else
-	. = ALIGN(8192);
+	. = ALIGN(THREAD_SIZE);
 	__data_loc = .;
 #endif
 
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index f6e6763..45c930c 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -10,6 +10,7 @@
 
 config ARCH_CDB89712
 	bool "CDB89712"
+	select ISA
 	help
 	  This is an evaluation board from Cirrus for the CS89712 processor.
 	  The board includes 2 serial ports, Ethernet, IRDA, and expansion
@@ -26,6 +27,8 @@
 
 config ARCH_EDB7211
 	bool "EDB7211"
+	select ISA
+	select DISCONTIGMEM
 	help
 	  Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
 	  evaluation board.
diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig
index 1090c68..324d9ed 100644
--- a/arch/arm/mach-footbridge/Kconfig
+++ b/arch/arm/mach-footbridge/Kconfig
@@ -5,6 +5,9 @@
 config ARCH_CATS
 	bool "CATS"
 	select FOOTBRIDGE_HOST
+	select ISA
+	select ISA_DMA
+	select PCI
 	help
 	  Say Y here if you intend to run this kernel on the CATS.
 
@@ -13,6 +16,9 @@
 config ARCH_PERSONAL_SERVER
 	bool "Compaq Personal Server"
 	select FOOTBRIDGE_HOST
+	select ISA
+	select ISA_DMA
+	select PCI
 	---help---
 	  Say Y here if you intend to run this kernel on the Compaq
 	  Personal Server.
@@ -42,6 +48,9 @@
 	bool "EBSA285 (host mode)"
 	select ARCH_EBSA285
 	select FOOTBRIDGE_HOST
+	select ISA
+	select ISA_DMA
+	select PCI
 	help
 	  Say Y here if you intend to run this kernel on the EBSA285 card
 	  in host ("central function") mode.
@@ -51,6 +60,9 @@
 config ARCH_NETWINDER
 	bool "NetWinder"
 	select FOOTBRIDGE_HOST
+	select ISA
+	select ISA_DMA
+	select PCI
 	help
 	  Say Y here if you intend to run this kernel on the Rebel.COM
 	  NetWinder.  Information about this machine can be found at:
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ec85813..cddd194 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -4,6 +4,7 @@
 config ARCH_MX1ADS
 	bool "mx1ads"
 	depends on ARCH_IMX
+	select ISA
 	help
 	  Say Y here if you are using the Motorola MX1ADS board
 
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 54377d0..41e5849 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 
 #include <asm/mach/map.h>
@@ -228,6 +229,14 @@
 	.resource	= imx_uart2_resources,
 };
 
+static struct imxfb_mach_info imx_fb_info;
+
+void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
+{
+	memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info));
+}
+EXPORT_SYMBOL(set_imx_fb_info);
+
 static struct resource imxfb_resources[] = {
 	[0] = {
 		.start	= 0x00205000,
@@ -241,9 +250,16 @@
 	},
 };
 
+static u64 fb_dma_mask = ~(u64)0;
+
 static struct platform_device imxfb_device = {
 	.name		= "imx-fb",
 	.id		= 0,
+	.dev		= {
+ 		.platform_data	= &imx_fb_info,
+		.dma_mask	= &fb_dma_mask,
+		.coherent_dma_mask = 0xffffffff,
+	},
 	.num_resources	= ARRAY_SIZE(imxfb_resources),
 	.resource	= imxfb_resources,
 };
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 86c50c3..bd17b51 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -216,7 +216,9 @@
 
 	write_seqlock(&xtime_lock);
 
-	// ...clear the interrupt
+	/*
+	 * clear the interrupt
+	 */
 	timer1->TimerClear = 1;
 
 	timer_tick(regs);
@@ -264,7 +266,7 @@
 	timer1->TimerValue   = timer_reload;
 	timer1->TimerControl = timer_ctrl;
 
-	/* 
+	/*
 	 * Make irqs happen for the system timer
 	 */
 	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 68e15c3..3b948e8 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -420,7 +420,22 @@
  */
 static void cp_clcd_enable(struct clcd_fb *fb)
 {
-	cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA);
+	u32 val;
+
+	if (fb->fb.var.bits_per_pixel <= 8)
+		val = CM_CTRL_LCDMUXSEL_VGA_8421BPP;
+	else if (fb->fb.var.bits_per_pixel <= 16)
+		val = CM_CTRL_LCDMUXSEL_VGA_16BPP;
+	else
+		val = 0; /* no idea for this, don't trust the docs */
+
+	cm_control(CM_CTRL_LCDMUXSEL_MASK|
+		   CM_CTRL_LCDEN0|
+		   CM_CTRL_LCDEN1|
+		   CM_CTRL_STATIC1|
+		   CM_CTRL_STATIC2|
+		   CM_CTRL_STATIC|
+		   CM_CTRL_n24BITEN, val);
 }
 
 static unsigned long framesize = SZ_1M;
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
index 9d182b7..d2c0ab2 100644
--- a/arch/arm/mach-integrator/leds.c
+++ b/arch/arm/mach-integrator/leds.c
@@ -37,7 +37,7 @@
 	unsigned long flags;
 	const unsigned int dbg_base = IO_ADDRESS(INTEGRATOR_DBG_BASE);
 	unsigned int update_alpha_leds;
-	
+
 	// yup, change the LEDs
 	local_irq_save(flags);
 	update_alpha_leds = 0;
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
index 20729de..1a844ca 100644
--- a/arch/arm/mach-integrator/time.c
+++ b/arch/arm/mach-integrator/time.c
@@ -40,25 +40,32 @@
 	return 1;
 }
 
-static void rtc_read_alarm(struct rtc_wkalrm *alrm)
+static int rtc_read_alarm(struct rtc_wkalrm *alrm)
 {
 	rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time);
+	return 0;
 }
 
-static int rtc_set_alarm(struct rtc_wkalrm *alrm)
+static inline int rtc_set_alarm(struct rtc_wkalrm *alrm)
 {
 	unsigned long time;
 	int ret;
 
-	ret = rtc_tm_to_time(&alrm->time, &time);
+	/*
+	 * At the moment, we can only deal with non-wildcarded alarm times.
+	 */
+	ret = rtc_valid_tm(&alrm->time);
+	if (ret == 0)
+		ret = rtc_tm_to_time(&alrm->time, &time);
 	if (ret == 0)
 		writel(time, rtc_base + RTC_MR);
 	return ret;
 }
 
-static void rtc_read_time(struct rtc_time *tm)
+static int rtc_read_time(struct rtc_time *tm)
 {
 	rtc_time_to_tm(readl(rtc_base + RTC_DR), tm);
+	return 0;
 }
 
 /*
@@ -69,7 +76,7 @@
  * edge of the 1Hz clock, we must write the time one second
  * in advance.
  */
-static int rtc_set_time(struct rtc_time *tm)
+static inline int rtc_set_time(struct rtc_time *tm)
 {
 	unsigned long time;
 	int ret;
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index c4683aa..aec13c7 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -65,19 +65,102 @@
 /*************************************************************************
  * IXDP2800 PCI
  *************************************************************************/
+static void __init ixdp2800_slave_disable_pci_master(void)
+{
+	*IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+}
+
+static void __init ixdp2800_master_wait_for_slave(void)
+{
+	volatile u32 *addr;
+
+	printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure "
+			 "its BAR sizes\n");
+
+	addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
+					PCI_BASE_ADDRESS_1);
+	do {
+		*addr = 0xffffffff;
+		cpu_relax();
+	} while (*addr != 0xfe000008);
+
+	addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
+					PCI_BASE_ADDRESS_2);
+	do {
+		*addr = 0xffffffff;
+		cpu_relax();
+	} while (*addr != 0xc0000008);
+
+	/*
+	 * Configure the slave's SDRAM BAR by hand.
+	 */
+	*addr = 0x40000008;
+}
+
+static void __init ixdp2800_slave_wait_for_master_enable(void)
+{
+	printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n");
+
+	while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0)
+		cpu_relax();
+}
+
 void __init ixdp2800_pci_preinit(void)
 {
 	printk("ixdp2x00_pci_preinit called\n");
 
-	*IXP2000_PCI_ADDR_EXT =  0x0000e000;
+	*IXP2000_PCI_ADDR_EXT = 0x0001e000;
 
-	*IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
+	if (!ixdp2x00_master_npu())
+		ixdp2800_slave_disable_pci_master();
+
 	*IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
+	*IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
 
 	ixp2000_pci_preinit();
+
+	if (ixdp2x00_master_npu()) {
+		/*
+		 * Wait until the slave set its SRAM/SDRAM BAR sizes
+		 * correctly before we proceed to scan and enumerate
+		 * the bus.
+		 */
+		ixdp2800_master_wait_for_slave();
+
+		/*
+		 * We configure the SDRAM BARs by hand because they
+		 * are 1G and fall outside of the regular allocated
+		 * PCI address space.
+		 */
+		*IXP2000_PCI_SDRAM_BAR = 0x00000008;
+	} else {
+		/*
+		 * Wait for the master to complete scanning the bus
+		 * and assigning resources before we proceed to scan
+		 * the bus ourselves.  Set pci=firmware to honor the
+		 * master's resource assignment.
+		 */
+		ixdp2800_slave_wait_for_master_enable();
+		pcibios_setup("firmware");
+	}
 }
 
-int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
+/*
+ * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside
+ * of the regular PCI window, because there's only 512M of outbound PCI
+ * memory window on each IXP, while we need 1G for each of the BARs.
+ */
+static void __devinit ixp2800_pci_fixup(struct pci_dev *dev)
+{
+	if (machine_is_ixdp2800()) {
+		dev->resource[2].start = 0;
+		dev->resource[2].end   = 0;
+		dev->resource[2].flags = 0;
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, ixp2800_pci_fixup);
+
+static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
 {
 	sys->mem_offset = 0x00000000;
 
@@ -129,22 +212,47 @@
 	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
 }
 
-static void ixdp2800_pci_postinit(void)
+static void __init ixdp2800_master_enable_slave(void)
 {
-	struct pci_dev *dev;
+	volatile u32 *addr;
 
-	if (ixdp2x00_master_npu()) {
-		dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
-		pci_remove_bus_device(dev);
-	} else {
-		dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
-		pci_remove_bus_device(dev);
+	printk(KERN_INFO "IXDP2800: enabling slave NPU\n");
 
+	addr = (volatile u32 *)ixp2000_pci_config_addr(0,
+					IXDP2X00_SLAVE_NPU_DEVFN,
+					PCI_COMMAND);
+
+	*addr |= PCI_COMMAND_MASTER;
+}
+
+static void __init ixdp2800_master_wait_for_slave_bus_scan(void)
+{
+	volatile u32 *addr;
+
+	printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n");
+
+	addr = (volatile u32 *)ixp2000_pci_config_addr(0,
+					IXDP2X00_SLAVE_NPU_DEVFN,
+					PCI_COMMAND);
+	while ((*addr & PCI_COMMAND_MEMORY) == 0)
+		cpu_relax();
+}
+
+static void __init ixdp2800_slave_signal_bus_scan_completion(void)
+{
+	printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n");
+	*IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY;
+}
+
+static void __init ixdp2800_pci_postinit(void)
+{
+	if (!ixdp2x00_master_npu()) {
 		ixdp2x00_slave_pci_postinit();
+		ixdp2800_slave_signal_bus_scan_completion();
 	}
 }
 
-struct hw_pci ixdp2800_pci __initdata = {
+struct __initdata hw_pci ixdp2800_pci __initdata = {
 	.nr_controllers	= 1,
 	.setup		= ixdp2800_pci_setup,
 	.preinit	= ixdp2800_pci_preinit,
@@ -155,8 +263,21 @@
 
 int __init ixdp2800_pci_init(void)
 {
-	if (machine_is_ixdp2800())
+	if (machine_is_ixdp2800()) {
+		struct pci_dev *dev;
+
 		pci_common_init(&ixdp2800_pci);
+		if (ixdp2x00_master_npu()) {
+			dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+			pci_remove_bus_device(dev);
+
+			ixdp2800_master_enable_slave();
+			ixdp2800_master_wait_for_slave_bus_scan();
+		} else {
+			dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+			pci_remove_bus_device(dev);
+		}
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index 831f8ff..5ff2f27 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -37,7 +37,7 @@
 
 static int clear_master_aborts(void);
 
-static u32 *
+u32 *
 ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
 {
 	u32 *paddress;
@@ -208,15 +208,15 @@
  * use our own resource space.
  */
 static struct resource ixp2000_pci_mem_space = {
-	.start	= 0x00000000,
+	.start	= 0xe0000000,
 	.end	= 0xffffffff,
 	.flags	= IORESOURCE_MEM,
 	.name	= "PCI Mem Space"
 };
 
 static struct resource ixp2000_pci_io_space = {
-	.start	= 0x00000000,
-	.end	= 0xffffffff,
+	.start	= 0x00010000,
+	.end	= 0x0001ffff,
 	.flags	= IORESOURCE_IO,
 	.name	= "PCI I/O Space"
 };
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 94bcdb9..aa92e37 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -502,15 +502,6 @@
 }
     
 int
-pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	if (mask >= SZ_64M - 1 )
-		return 0;
-
-	return -EIO;
-}
-
-int
 pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 {
 	if (mask >= SZ_64M - 1 )
@@ -520,7 +511,6 @@
 }
 
 EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_dac_set_dma_mask);
 EXPORT_SYMBOL(pci_set_consistent_dma_mask);
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index b1575b8..a45aaa1 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -220,6 +220,30 @@
 	.id		= 2,
 };
 
+static struct resource i2c_resources[] = {
+	{
+		.start	= 0x40301680,
+		.end	= 0x403016a3,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_I2C,
+		.end	= IRQ_I2C,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device i2c_device = {
+	.name		= "pxa2xx-i2c",
+	.id		= 0,
+	.resource	= i2c_resources,
+	.num_resources	= ARRAY_SIZE(i2c_resources),
+};
+
+void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
+{
+	i2c_device.dev.platform_data = info;
+}
+
 static struct platform_device *devices[] __initdata = {
 	&pxamci_device,
 	&udc_device,
@@ -227,6 +251,7 @@
 	&ffuart_device,
 	&btuart_device,
 	&stuart_device,
+	&i2c_device,
 };
 
 static int __init pxa_init(void)
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 16cad2c..5786cca 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -18,6 +18,11 @@
 
 #include <asm/arch/pxa-regs.h>
 
+#ifdef CONFIG_PXA27x			// workaround for Errata 50
+#define MDREFR_KDIV	0x200a4000	// all banks
+#define CCCR_SLEEP	0x00000107	// L=7 2N=2 A=0 PPDIS=0 CPDIS=0
+#endif
+
 		.text
 
 /*
@@ -28,7 +33,9 @@
 
 ENTRY(pxa_cpu_suspend)
 
+#ifndef CONFIG_IWMMXT
 	mra	r2, r3, acc0
+#endif
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
 
 	@ get coprocessor registers
@@ -61,14 +68,23 @@
 	@ prepare value for sleep mode
 	mov	r1, #3				@ sleep mode
 
-	@ prepare to put SDRAM into self-refresh manually
-	ldr	r4, =MDREFR
-	ldr	r5, [r4]
-	orr	r5, r5, #MDREFR_SLFRSH
-
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
 
+	@ prepare SDRAM refresh settings
+	ldr	r4, =MDREFR
+	ldr	r5, [r4]
+
+	@ enable SDRAM self-refresh mode
+	orr	r5, r5, #MDREFR_SLFRSH
+
+#ifdef CONFIG_PXA27x
+	@ set SDCLKx divide-by-2 bits (this is part of a workaround for Errata 50)
+	ldr	r6, =MDREFR_KDIV
+	orr	r5, r5, r6
+#endif
+
+#ifdef CONFIG_PXA25x
 	@ Intel PXA255 Specification Update notes problems
 	@ about suspending with PXBus operating above 133MHz
 	@ (see Errata 31, GPIO output signals, ... unpredictable in sleep
@@ -100,6 +116,18 @@
 	mov	r0, #0
 	mcr	p14, 0, r0, c6, c0, 0
 	orr	r0, r0, #2			@ initiate change bit
+#endif
+#ifdef CONFIG_PXA27x
+	@ Intel PXA270 Specification Update notes problems sleeping
+	@ with core operating above 91 MHz
+	@ (see Errata 50, ...processor does not exit from sleep...)
+
+	ldr	r6, =CCCR
+	ldr	r8, [r6]		@ keep original value for resume
+
+	ldr	r7, =CCCR_SLEEP		@ prepare CCCR sleep value
+	mov	r0, #0x2		@ prepare value for CLKCFG
+#endif
 
 	@ align execution to a cache line
 	b	1f
@@ -111,6 +139,7 @@
 	@ All needed values are now in registers.
 	@ These last instructions should be in cache
 
+#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
 	@ initiate the frequency change...
 	str	r7, [r6]
 	mcr	p14, 0, r0, c6, c0, 0
@@ -118,14 +147,27 @@
 	@ restore the original cpu speed value for resume
 	str	r8, [r6]
 
-	@ put SDRAM into self-refresh
-	str	r5, [r4]
+	@ need 6 13-MHz cycles before changing PWRMODE
+	@ just set frequency to 91-MHz... 6*91/13 = 42
+
+	mov	r0, #42
+10:	subs	r0, r0, #1
+	bne	10b
+#endif
+
+	@ Do not reorder...
+	@ Intel PXA270 Specification Update notes problems performing
+	@ external accesses after SDRAM is put in self-refresh mode
+	@ (see Errata 39 ...hangs when entering self-refresh mode)
 
 	@ force address lines low by reading at physical address 0
 	ldr	r3, [r2]
 
+	@ put SDRAM into self-refresh
+	str	r5, [r4]
+
 	@ enter sleep mode
-	mcr	p14, 0, r1, c7, c0, 0
+	mcr	p14, 0, r1, c7, c0, 0		@ PWRMODE
 
 20:	b	20b				@ loop waiting for sleep
 
@@ -188,7 +230,9 @@
 	bl	cpu_xscale_proc_init
 #endif
 	ldmfd	sp!, {r2, r3}
+#ifndef CONFIG_IWMMXT
 	mar	acc0, r2, r3
+#endif
 	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
 
 
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5b670c9..c4fc6be 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -409,3 +409,24 @@
 	depends on CPU_ARM1020
 	help
 	  Say Y here to disable branch prediction.  If unsure, say N.
+
+config TLS_REG_EMUL
+	bool
+	default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+	help
+	  We might be running on an ARMv6+ processor which should have the TLS
+	  register but for some reason we can't use it, or maybe an SMP system
+	  using a pre-ARMv6 processor (there are apparently a few prototypes
+	  like that in existence) and therefore access to that register must
+	  be emulated.
+
+config HAS_TLS_REG
+	bool
+	depends on CPU_32v6
+	default y if !TLS_REG_EMUL
+	help
+	  This selects support for the CP15 thread register.
+	  It is defined to be available on ARMv6 or later.  If a particular
+	  ARMv6 or later CPU doesn't support it then it must omc;ide "select
+	  TLS_REG_EMUL" along with its other caracteristics.
+
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index 38b2cbb..8f76f3d 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -1,5 +1,6 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include "abort-macro.S"
 /*
  * Function: v6_early_abort
  *
@@ -13,11 +14,26 @@
  *	   : sp = pointer to registers
  *
  * Purpose : obtain information about current aborted instruction.
+ * Note: we read user space.  This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture.  Unfortunately, this does happen.  We live with it.
  */
 	.align	5
 ENTRY(v6_early_abort)
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
+/*
+ * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR.
+ * The test below covers all the write situations, including Java bytecodes
+ */
+	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
+	tst	r3, #PSR_J_BIT			@ Java?
+	movne	pc, lr
+	do_thumb_abort
+	ldreq	r3, [r2]			@ read aborted ARM instruction
+	do_ldrd_abort
+	tst	r3, #1 << 20			@ L = 0 -> write
+	orreq	r1, r1, #1 << 11		@ yes.
 	mov	pc, lr
 
 
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index f5a87db8..585dfb8 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -411,9 +411,10 @@
 		mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4;
 		mem_types[MT_ROM].prot_sect &= ~PMD_BIT4;
 		/*
-		 * Mark cache clean areas read only from SVC mode
-		 * and no access from userspace.
+		 * Mark cache clean areas and XIP ROM read only
+		 * from SVC mode and no access from userspace.
 		 */
+		mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 		mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 	}
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 3955de5..6caed90 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -89,6 +89,10 @@
           machine with 4MB of memory.
 endmenu
 
+config ISA_DMA_API
+	bool
+	default y
+
 menu "General setup"
 
 # Compressed boot loader in ROM.  Yes, we really want to ask about
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 2a13714..8a52124 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -591,7 +592,7 @@
 		case PTRACE_SYSCALL:
 		case PTRACE_CONT:
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			if (request == PTRACE_SYSCALL)
 				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -626,7 +627,7 @@
 		 */
 		case PTRACE_SINGLESTEP:
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			child->ptrace |= PT_SINGLESTEP;
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff --git a/arch/arm26/mm/small_page.c b/arch/arm26/mm/small_page.c
index 77be86c..3044710 100644
--- a/arch/arm26/mm/small_page.c
+++ b/arch/arm26/mm/small_page.c
@@ -92,8 +92,7 @@
 		page = list_entry(order->queue.next, struct page, lru);
 again:
 #ifdef PEDANTIC
-		if (USED_MAP(page) & ~order->all_used)
-			PAGE_BUG(page);
+		BUG_ON(USED_MAP(page) & ~order->all_used);
 #endif
 		offset = ffz(USED_MAP(page));
 		SET_USED(page, offset);
@@ -141,8 +140,7 @@
 			goto non_small;
 
 #ifdef PEDANTIC
-		if (USED_MAP(page) & ~order->all_used)
-			PAGE_BUG(page);
+		BUG_ON(USED_MAP(page) & ~order->all_used);
 #endif
 
 		spage = spage >> order->shift;
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index da15db8..581ecab 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -184,7 +185,7 @@
 		case PTRACE_CONT:
 			ret = -EIO;
 			
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
                         
 			if (request == PTRACE_SYSCALL) {
@@ -219,7 +220,7 @@
 		case PTRACE_SINGLESTEP:
 			ret = -EIO;
 			
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index 2a0efb7..cbe03cb 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -20,6 +20,7 @@
 #include <linux/user.h>
 #include <linux/config.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -239,7 +240,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -267,7 +268,7 @@
 
 	case PTRACE_SINGLESTEP:  /* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		ptrace_enable(child);
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 5f19d77..05c15e8 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/config.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -171,7 +172,7 @@
 		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 		case PTRACE_CONT: { /* restart after signal. */
 			ret = -EIO;
-			if ((unsigned long) data >= _NSIG)
+			if (!valid_signal(data))
 				break ;
 			if (request == PTRACE_SYSCALL)
 				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -202,7 +203,7 @@
 
 		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			child->exit_code = data;
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 17a0cbc..e382f32 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -183,7 +183,7 @@
 	  - "Winchip-C6" for original IDT Winchip.
 	  - "Winchip-2" for IDT Winchip 2.
 	  - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
-	  - "MediaGX/Geode" for Cyrix MediaGX aka Geode.
+	  - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
 	  - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
 	  - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
 
@@ -311,12 +311,10 @@
 	  stores for this CPU, which can increase performance of some
 	  operations.
 
-config MGEODE
-	bool "MediaGX/Geode"
+config MGEODEGX1
+	bool "GeodeGX1"
 	help
-	  Select this for a Cyrix MediaGX aka Geode chip. Linux and GCC
-          treat this chip as a 586TSC with some extended instructions
-          and alignment reqirements.
+	  Select this for a Geode GX1 (Cyrix MediaGX) chip.
 
 config MCYRIXIII
 	bool "CyrixIII/VIA-C3"
@@ -368,7 +366,7 @@
 	int
 	default "7" if MPENTIUM4 || X86_GENERIC
 	default "4" if X86_ELAN || M486 || M386
-	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE
+	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
 	default "6" if MK7 || MK8 || MPENTIUMM
 
 config RWSEM_GENERIC_SPINLOCK
@@ -387,7 +385,7 @@
 
 config X86_PPRO_FENCE
 	bool
-	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODE
+	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1
 	default y
 
 config X86_F00F_BUG
@@ -417,7 +415,7 @@
 
 config X86_ALIGNMENT_16
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODE
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
 	default y
 
 config X86_GOOD_APIC
@@ -442,7 +440,7 @@
 
 config X86_OOSTORE
 	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MGEODE) && MTRR
+	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
 	default y
 
 config HPET_TIMER
@@ -578,7 +576,7 @@
 
 config X86_TSC
 	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODE) && !X86_NUMAQ
+	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
 	default y
 
 config X86_MCE
@@ -653,6 +651,24 @@
 	  Say Y if you intend to run this kernel on a Dell Inspiron 8000.
 	  Say N otherwise.
 
+config X86_REBOOTFIXUPS
+	bool "Enable X86 board specific fixups for reboot"
+	depends on X86
+	default n
+	---help---
+	  This enables chipset and/or board specific fixups to be done
+	  in order to get reboot to work correctly. This is only needed on
+	  some combinations of hardware and BIOS. The symptom, for which
+	  this config is intended, is when reboot ends with a stalled/hung
+	  system.
+
+	  Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1.
+	  combination.
+
+	  Say Y if you want to enable the fixup. Currently, it's safe to
+	  enable this option even if you don't need it.
+	  Say N otherwise.
+
 config MICROCODE
 	tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
 	---help---
@@ -1155,6 +1171,10 @@
 
 source "drivers/pci/Kconfig"
 
+config ISA_DMA_API
+	bool
+	default y
+
 config ISA
 	bool "ISA support"
 	depends on !(X86_VOYAGER || X86_VISWS)
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 314c714..1c36ca3 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -14,7 +14,7 @@
 # 19990713  Artur Skawina <skawina@geocities.com>
 #           Added '-march' and '-mpreferred-stack-boundary' support
 #
-#           Kianusch Sayah Karadji <kianusch@sk-tech.net>
+# 20050320  Kianusch Sayah Karadji <kianusch@sk-tech.net>
 #           Added support for GEODE CPU
 
 LDFLAGS		:= -m elf_i386
@@ -54,8 +54,8 @@
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)	+= -march=i486
 
-# MediaGX aka Geode support
-cflags-$(CONFIG_MGEODE)		+= $(call cc-option,-march=pentium-mmx,-march=i586)
+# Geode GX1 support
+cflags-$(CONFIG_MGEODEGX1)		+= $(call cc-option,-march=pentium-mmx,-march=i486)
 
 # -mregparm=3 works ok on gcc-3.0 and later
 #
@@ -123,7 +123,7 @@
 boot := arch/i386/boot
 
 .PHONY: zImage bzImage compressed zlilo bzlilo \
-	zdisk bzdisk fdimage fdimage144 fdimage288 install
+	zdisk bzdisk fdimage fdimage144 fdimage288 install kernel_install
 
 all: bzImage
 
@@ -145,8 +145,9 @@
 fdimage fdimage144 fdimage288: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
 
-install:
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
+install: vmlinux
+install kernel_install:
+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
 
 prepare: include/asm-$(ARCH)/asm_offsets.h
 CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
index ba9fe14d..011b7a4 100644
--- a/arch/i386/boot/bootsect.S
+++ b/arch/i386/boot/bootsect.S
@@ -83,7 +83,7 @@
 	.ascii	"\n"
 	.ascii	"Remove disk and press any key to reboot . . .\r\n"
 	.byte	0
-	
+
 
 	# Kernel attributes; used by setup
 
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index fa67045..cedc55c 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -12,7 +12,6 @@
 #include <linux/linkage.h>
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
-#include <video/edid.h>
 #include <asm/io.h>
 
 /*
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index a934ab3..caa1fde 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -164,7 +164,7 @@
 trampoline:	call	start_of_setup
 		.align 16
 					# The offset at this point is 0x240
-		.space	(0x7ff-0x240+1) # E820 & EDD space (ending at 0x7ff)
+		.space	(0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
 # End of setup header #####################################################
 
 start_of_setup:
@@ -333,9 +333,9 @@
 	# sizeof(e820rec).
 	#
 good820:
-	movb	(E820NR), %al			# up to 32 entries
+	movb	(E820NR), %al			# up to 128 entries
 	cmpb	$E820MAX, %al
-	jnl	bail820
+	jae	bail820
 
 	incb	(E820NR)
 	movw	%di, %ax
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 925d3f5..0587477 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -1924,36 +1924,36 @@
 	ret
 
 store_edid:
-	pushw	%es				# just save all registers 
-	pushw	%ax				
+	pushw	%es				# just save all registers
+	pushw	%ax
 	pushw	%bx
 	pushw   %cx
 	pushw	%dx
 	pushw   %di
 
-	pushw	%fs                             
+	pushw	%fs
 	popw    %es
 
 	movl	$0x13131313, %eax		# memset block with 0x13
 	movw    $32, %cx
 	movw	$0x140, %di
 	cld
-	rep 
-	stosl  
+	rep
+	stosl
 
-	movw	$0x4f15, %ax                    # do VBE/DDC 
+	movw	$0x4f15, %ax                    # do VBE/DDC
 	movw	$0x01, %bx
 	movw	$0x00, %cx
 	movw    $0x01, %dx
 	movw	$0x140, %di
-	int	$0x10	
+	int	$0x10
 
-	popw	%di				# restore all registers        
+	popw	%di				# restore all registers
 	popw	%dx
 	popw	%cx
 	popw	%bx
 	popw	%ax
-	popw	%es	
+	popw	%es
 	ret
 
 # VIDEO_SELECT-only variables
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index aacdae6..0fbcfe0 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
+obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 53eb5cf..848bb97 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -650,7 +650,7 @@
 	 */
 	rsdp_phys = acpi_scan_rsdp (0, 0x400);
 	if (!rsdp_phys)
-		rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
+		rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
 
 	return rsdp_phys;
 }
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index e3879f7..d509836 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -1265,8 +1265,6 @@
 
 	setup_local_APIC();
 
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		check_nmi_watchdog();
 #ifdef CONFIG_X86_IO_APIC
 	if (smp_found_config)
 		if (!skip_ioapic_setup && nr_ioapics)
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 8d182e8..16dbc41 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -24,7 +24,7 @@
 
 static void __init init_amd(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_SMP
 	int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
 #endif
 	u32 l, h;
@@ -198,7 +198,7 @@
 			c->x86_num_cores = 1;
 	}
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_SMP
 	/*
 	 * On a AMD dual core setup the lower bits of the APIC id
 	 * distingush the cores.  Assumes number of cores is a power
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
index 933b0dd..9027a98 100644
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c
@@ -218,12 +218,12 @@
 	mtrr_type type;
 } arr_state_t;
 
-static arr_state_t arr_state[8] __initdata = {
+static arr_state_t arr_state[8] __devinitdata = {
 	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
 	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
 };
 
-static unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char ccr_state[7] __devinitdata = { 0, 0, 0, 0, 0, 0, 0 };
 
 static void cyrix_set_all(void)
 {
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index 9f7a7ea..f468a97 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -124,8 +124,8 @@
 	return -ENOSPC;
 }
 
-void generic_get_mtrr(unsigned int reg, unsigned long *base,
-		      unsigned int *size, mtrr_type * type)
+static void generic_get_mtrr(unsigned int reg, unsigned long *base,
+			     unsigned int *size, mtrr_type * type)
 {
 	unsigned int mask_lo, mask_hi, base_lo, base_hi;
 
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 54999e4..e1c2042 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -72,17 +72,21 @@
 static int have_wrcomb(void)
 {
 	struct pci_dev *dev;
+	u8 rev;
 	
 	if ((dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) {
-		/* ServerWorks LE chipsets have problems with write-combining 
+		/* ServerWorks LE chipsets < rev 6 have problems with write-combining
 		   Don't allow it and leave room for other chipsets to be tagged */
 		if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
 		    dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) {
-			printk(KERN_INFO "mtrr: Serverworks LE detected. Write-combining disabled.\n");
-			pci_dev_put(dev);
-			return 0;
+			pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+			if (rev <= 5) {
+				printk(KERN_INFO "mtrr: Serverworks LE rev < 6 detected. Write-combining disabled.\n");
+				pci_dev_put(dev);
+				return 0;
+			}
 		}
-		/* Intel 450NX errata # 23. Non ascending cachline evictions to
+		/* Intel 450NX errata # 23. Non ascending cacheline evictions to
 		   write combining memory may resulting in data corruption */
 		if (dev->vendor == PCI_VENDOR_ID_INTEL &&
 		    dev->device == PCI_DEVICE_ID_INTEL_82451NX) {
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 4f28eba..7323c19 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -25,7 +25,7 @@
 	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
 
 		/* AMD-defined */
-		"pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
 		NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 3c73dc8..a991d4e 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -260,11 +260,9 @@
 .section .fixup,"ax"
 iret_exc:
 	sti
-	movl $__USER_DS, %edx
-	movl %edx, %ds
-	movl %edx, %es
-	movl $11,%eax
-	call do_exit
+	pushl $0			# no error code
+	pushl $do_iret_error
+	jmp error_code
 .previous
 .section __ex_table,"a"
 	.align 4
@@ -516,8 +514,6 @@
 	xorl %edx,%edx			# error code 0
 	movl %esp,%eax			# pt_regs pointer
 	call do_debug
-	testl %eax,%eax
-	jnz restore_all
 	jmp ret_from_exception
 
 /*
@@ -598,8 +594,6 @@
 	xorl %edx,%edx		# zero error code
 	movl %esp,%eax		# pt_regs pointer
 	call do_int3
-	testl %eax,%eax
-	jnz restore_all
 	jmp ret_from_exception
 
 ENTRY(overflow)
@@ -658,296 +652,6 @@
 	pushl $do_spurious_interrupt_bug
 	jmp error_code
 
-.data
-ENTRY(sys_call_table)
-	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
-	.long sys_exit
-	.long sys_fork
-	.long sys_read
-	.long sys_write
-	.long sys_open		/* 5 */
-	.long sys_close
-	.long sys_waitpid
-	.long sys_creat
-	.long sys_link
-	.long sys_unlink	/* 10 */
-	.long sys_execve
-	.long sys_chdir
-	.long sys_time
-	.long sys_mknod
-	.long sys_chmod		/* 15 */
-	.long sys_lchown16
-	.long sys_ni_syscall	/* old break syscall holder */
-	.long sys_stat
-	.long sys_lseek
-	.long sys_getpid	/* 20 */
-	.long sys_mount
-	.long sys_oldumount
-	.long sys_setuid16
-	.long sys_getuid16
-	.long sys_stime		/* 25 */
-	.long sys_ptrace
-	.long sys_alarm
-	.long sys_fstat
-	.long sys_pause
-	.long sys_utime		/* 30 */
-	.long sys_ni_syscall	/* old stty syscall holder */
-	.long sys_ni_syscall	/* old gtty syscall holder */
-	.long sys_access
-	.long sys_nice
-	.long sys_ni_syscall	/* 35 - old ftime syscall holder */
-	.long sys_sync
-	.long sys_kill
-	.long sys_rename
-	.long sys_mkdir
-	.long sys_rmdir		/* 40 */
-	.long sys_dup
-	.long sys_pipe
-	.long sys_times
-	.long sys_ni_syscall	/* old prof syscall holder */
-	.long sys_brk		/* 45 */
-	.long sys_setgid16
-	.long sys_getgid16
-	.long sys_signal
-	.long sys_geteuid16
-	.long sys_getegid16	/* 50 */
-	.long sys_acct
-	.long sys_umount	/* recycled never used phys() */
-	.long sys_ni_syscall	/* old lock syscall holder */
-	.long sys_ioctl
-	.long sys_fcntl		/* 55 */
-	.long sys_ni_syscall	/* old mpx syscall holder */
-	.long sys_setpgid
-	.long sys_ni_syscall	/* old ulimit syscall holder */
-	.long sys_olduname
-	.long sys_umask		/* 60 */
-	.long sys_chroot
-	.long sys_ustat
-	.long sys_dup2
-	.long sys_getppid
-	.long sys_getpgrp	/* 65 */
-	.long sys_setsid
-	.long sys_sigaction
-	.long sys_sgetmask
-	.long sys_ssetmask
-	.long sys_setreuid16	/* 70 */
-	.long sys_setregid16
-	.long sys_sigsuspend
-	.long sys_sigpending
-	.long sys_sethostname
-	.long sys_setrlimit	/* 75 */
-	.long sys_old_getrlimit
-	.long sys_getrusage
-	.long sys_gettimeofday
-	.long sys_settimeofday
-	.long sys_getgroups16	/* 80 */
-	.long sys_setgroups16
-	.long old_select
-	.long sys_symlink
-	.long sys_lstat
-	.long sys_readlink	/* 85 */
-	.long sys_uselib
-	.long sys_swapon
-	.long sys_reboot
-	.long old_readdir
-	.long old_mmap		/* 90 */
-	.long sys_munmap
-	.long sys_truncate
-	.long sys_ftruncate
-	.long sys_fchmod
-	.long sys_fchown16	/* 95 */
-	.long sys_getpriority
-	.long sys_setpriority
-	.long sys_ni_syscall	/* old profil syscall holder */
-	.long sys_statfs
-	.long sys_fstatfs	/* 100 */
-	.long sys_ioperm
-	.long sys_socketcall
-	.long sys_syslog
-	.long sys_setitimer
-	.long sys_getitimer	/* 105 */
-	.long sys_newstat
-	.long sys_newlstat
-	.long sys_newfstat
-	.long sys_uname
-	.long sys_iopl		/* 110 */
-	.long sys_vhangup
-	.long sys_ni_syscall	/* old "idle" system call */
-	.long sys_vm86old
-	.long sys_wait4
-	.long sys_swapoff	/* 115 */
-	.long sys_sysinfo
-	.long sys_ipc
-	.long sys_fsync
-	.long sys_sigreturn
-	.long sys_clone		/* 120 */
-	.long sys_setdomainname
-	.long sys_newuname
-	.long sys_modify_ldt
-	.long sys_adjtimex
-	.long sys_mprotect	/* 125 */
-	.long sys_sigprocmask
-	.long sys_ni_syscall	/* old "create_module" */ 
-	.long sys_init_module
-	.long sys_delete_module
-	.long sys_ni_syscall	/* 130:	old "get_kernel_syms" */
-	.long sys_quotactl
-	.long sys_getpgid
-	.long sys_fchdir
-	.long sys_bdflush
-	.long sys_sysfs		/* 135 */
-	.long sys_personality
-	.long sys_ni_syscall	/* reserved for afs_syscall */
-	.long sys_setfsuid16
-	.long sys_setfsgid16
-	.long sys_llseek	/* 140 */
-	.long sys_getdents
-	.long sys_select
-	.long sys_flock
-	.long sys_msync
-	.long sys_readv		/* 145 */
-	.long sys_writev
-	.long sys_getsid
-	.long sys_fdatasync
-	.long sys_sysctl
-	.long sys_mlock		/* 150 */
-	.long sys_munlock
-	.long sys_mlockall
-	.long sys_munlockall
-	.long sys_sched_setparam
-	.long sys_sched_getparam   /* 155 */
-	.long sys_sched_setscheduler
-	.long sys_sched_getscheduler
-	.long sys_sched_yield
-	.long sys_sched_get_priority_max
-	.long sys_sched_get_priority_min  /* 160 */
-	.long sys_sched_rr_get_interval
-	.long sys_nanosleep
-	.long sys_mremap
-	.long sys_setresuid16
-	.long sys_getresuid16	/* 165 */
-	.long sys_vm86
-	.long sys_ni_syscall	/* Old sys_query_module */
-	.long sys_poll
-	.long sys_nfsservctl
-	.long sys_setresgid16	/* 170 */
-	.long sys_getresgid16
-	.long sys_prctl
-	.long sys_rt_sigreturn
-	.long sys_rt_sigaction
-	.long sys_rt_sigprocmask	/* 175 */
-	.long sys_rt_sigpending
-	.long sys_rt_sigtimedwait
-	.long sys_rt_sigqueueinfo
-	.long sys_rt_sigsuspend
-	.long sys_pread64	/* 180 */
-	.long sys_pwrite64
-	.long sys_chown16
-	.long sys_getcwd
-	.long sys_capget
-	.long sys_capset	/* 185 */
-	.long sys_sigaltstack
-	.long sys_sendfile
-	.long sys_ni_syscall	/* reserved for streams1 */
-	.long sys_ni_syscall	/* reserved for streams2 */
-	.long sys_vfork		/* 190 */
-	.long sys_getrlimit
-	.long sys_mmap2
-	.long sys_truncate64
-	.long sys_ftruncate64
-	.long sys_stat64	/* 195 */
-	.long sys_lstat64
-	.long sys_fstat64
-	.long sys_lchown
-	.long sys_getuid
-	.long sys_getgid	/* 200 */
-	.long sys_geteuid
-	.long sys_getegid
-	.long sys_setreuid
-	.long sys_setregid
-	.long sys_getgroups	/* 205 */
-	.long sys_setgroups
-	.long sys_fchown
-	.long sys_setresuid
-	.long sys_getresuid
-	.long sys_setresgid	/* 210 */
-	.long sys_getresgid
-	.long sys_chown
-	.long sys_setuid
-	.long sys_setgid
-	.long sys_setfsuid	/* 215 */
-	.long sys_setfsgid
-	.long sys_pivot_root
-	.long sys_mincore
-	.long sys_madvise
-	.long sys_getdents64	/* 220 */
-	.long sys_fcntl64
-	.long sys_ni_syscall	/* reserved for TUX */
-	.long sys_ni_syscall
-	.long sys_gettid
-	.long sys_readahead	/* 225 */
-	.long sys_setxattr
-	.long sys_lsetxattr
-	.long sys_fsetxattr
-	.long sys_getxattr
-	.long sys_lgetxattr	/* 230 */
-	.long sys_fgetxattr
-	.long sys_listxattr
-	.long sys_llistxattr
-	.long sys_flistxattr
-	.long sys_removexattr	/* 235 */
-	.long sys_lremovexattr
-	.long sys_fremovexattr
-	.long sys_tkill
-	.long sys_sendfile64
-	.long sys_futex		/* 240 */
-	.long sys_sched_setaffinity
-	.long sys_sched_getaffinity
-	.long sys_set_thread_area
-	.long sys_get_thread_area
-	.long sys_io_setup	/* 245 */
-	.long sys_io_destroy
-	.long sys_io_getevents
-	.long sys_io_submit
-	.long sys_io_cancel
-	.long sys_fadvise64	/* 250 */
-	.long sys_ni_syscall
-	.long sys_exit_group
-	.long sys_lookup_dcookie
-	.long sys_epoll_create
-	.long sys_epoll_ctl	/* 255 */
-	.long sys_epoll_wait
- 	.long sys_remap_file_pages
- 	.long sys_set_tid_address
- 	.long sys_timer_create
- 	.long sys_timer_settime		/* 260 */
- 	.long sys_timer_gettime
- 	.long sys_timer_getoverrun
- 	.long sys_timer_delete
- 	.long sys_clock_settime
- 	.long sys_clock_gettime		/* 265 */
- 	.long sys_clock_getres
- 	.long sys_clock_nanosleep
-	.long sys_statfs64
-	.long sys_fstatfs64	
-	.long sys_tgkill	/* 270 */
-	.long sys_utimes
- 	.long sys_fadvise64_64
-	.long sys_ni_syscall	/* sys_vserver */
-	.long sys_mbind
-	.long sys_get_mempolicy
-	.long sys_set_mempolicy
-	.long sys_mq_open
-	.long sys_mq_unlink
-	.long sys_mq_timedsend
-	.long sys_mq_timedreceive	/* 280 */
-	.long sys_mq_notify
-	.long sys_mq_getsetattr
-	.long sys_ni_syscall		/* reserved for kexec */
-	.long sys_waitid
-	.long sys_ni_syscall		/* 285 */ /* available */
-	.long sys_add_key
-	.long sys_request_key
-	.long sys_keyctl
+#include "syscall_table.S"
 
 syscall_table_size=(.-sys_call_table)
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index d273fd7..e966fc8 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -380,6 +380,7 @@
 	ALIGN
 ignore_int:
 	cld
+#ifdef CONFIG_PRINTK
 	pushl %eax
 	pushl %ecx
 	pushl %edx
@@ -400,6 +401,7 @@
 	popl %edx
 	popl %ecx
 	popl %eax
+#endif
 	iret
 
 /*
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 14ec354..903190a 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -169,10 +169,6 @@
 EXPORT_SYMBOL_GPL(set_nmi_callback);
 EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
-#undef memcmp
-extern int memcmp(const void *,const void *,__kernel_size_t);
-EXPORT_SYMBOL(memcmp);
-
 EXPORT_SYMBOL(register_die_notifier);
 #ifdef CONFIG_HAVE_DEC_LOCK
 EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 5e0d55b..7a324e8 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2175,7 +2175,6 @@
 				disable_8259A_irq(0);
 				setup_nmi();
 				enable_8259A_irq(0);
-				check_nmi_watchdog();
 			}
 			return;
 		}
@@ -2198,7 +2197,6 @@
 				add_pin_to_irq(0, 0, pin2);
 			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				check_nmi_watchdog();
 			}
 			return;
 		}
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 6716816..59ff9b4 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -217,6 +217,13 @@
 		*tos &= ~(TF_MASK | IF_MASK);
 		*tos |= kprobe_old_eflags;
 		break;
+	case 0xc3:		/* ret/lret */
+	case 0xcb:
+	case 0xc2:
+	case 0xca:
+		regs->eflags &= ~TF_MASK;
+		/* eip is already adjusted, no more changes required*/
+		return;
 	case 0xe8:		/* call relative - Fix return addr */
 		*tos = orig_eip + (*tos - copy_eip);
 		break;
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 2f89d00..2c0ee9c 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -102,20 +102,21 @@
 	(P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
 	 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
 
-int __init check_nmi_watchdog (void)
+static int __init check_nmi_watchdog(void)
 {
 	unsigned int prev_nmi_count[NR_CPUS];
 	int cpu;
 
-	printk(KERN_INFO "testing NMI watchdog ... ");
+	if (nmi_watchdog == NMI_NONE)
+		return 0;
+
+	printk(KERN_INFO "Testing NMI watchdog ... ");
 
 	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
 	local_irq_enable();
 	mdelay((10*1000)/nmi_hz); // wait 10 ticks
 
-	/* FIXME: Only boot CPU is online at this stage.  Check CPUs
-           as they come up. */
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 #ifdef CONFIG_SMP
 		/* Check cpu_callin_map here because that is set
@@ -139,6 +140,8 @@
 
 	return 0;
 }
+/* This needs to happen later in boot so counters are working */
+late_initcall(check_nmi_watchdog);
 
 static int __init setup_nmi_watchdog(char *str)
 {
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index b2203e2..96e3ea6 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -400,11 +400,6 @@
 	int err;
 
 	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
-	*childregs = *regs;
-	childregs->eax = 0;
-	childregs->esp = esp;
-
-	p->thread.esp = (unsigned long) childregs;
 	/*
 	 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
 	 * This is necessary to guarantee that the entire "struct pt_regs"
@@ -415,7 +410,13 @@
 	 * "struct pt_regs" is possible, but they may contain the
 	 * completely wrong values.
 	 */
-	p->thread.esp0 = (unsigned long) (childregs+1) - 8;
+	childregs = (struct pt_regs *) ((unsigned long) childregs - 8);
+	*childregs = *regs;
+	childregs->eax = 0;
+	childregs->esp = esp;
+
+	p->thread.esp = (unsigned long) childregs;
+	p->thread.esp0 = (unsigned long) (childregs+1);
 
 	p->thread.eip = (unsigned long) ret_from_fork;
 
@@ -611,8 +612,8 @@
 	 * Save away %fs and %gs. No need to save %es and %ds, as
 	 * those are always kernel segments while inside the kernel.
 	 */
-	asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
-	asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
+	asm volatile("mov %%fs,%0":"=m" (prev->fs));
+	asm volatile("mov %%gs,%0":"=m" (prev->gs));
 
 	/*
 	 * Restore %fs and %gs if needed.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index b2f1764..e34f651 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -16,6 +16,7 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -511,7 +512,7 @@
 	case PTRACE_SYSCALL:	/* continue and stop at next (return from) syscall */
 	case PTRACE_CONT:	/* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL) {
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -543,7 +544,7 @@
 
 	case PTRACE_SINGLESTEP:	/* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		set_singlestep(child);
@@ -682,24 +683,18 @@
 	/* do the secure computing check first */
 	secure_computing(regs->orig_eax);
 
-	if (unlikely(current->audit_context)) {
-		if (!entryexit)
-			audit_syscall_entry(current, regs->orig_eax,
-					    regs->ebx, regs->ecx,
-					    regs->edx, regs->esi);
-		else
-			audit_syscall_exit(current, regs->eax);
-	}
+	if (unlikely(current->audit_context) && entryexit)
+		audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
 
 	if (!(current->ptrace & PT_PTRACED))
-		return;
+		goto out;
 
 	/* Fake a debug trap */
 	if (test_thread_flag(TIF_SINGLESTEP))
 		send_sigtrap(current, regs, 0);
 
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
+		goto out;
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
@@ -714,4 +709,9 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
+ out:
+	if (unlikely(current->audit_context) && !entryexit)
+		audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
+				    regs->ebx, regs->ecx, regs->edx, regs->esi);
+
 }
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 3d7e994..6dc27eb 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -13,6 +13,7 @@
 #include <asm/uaccess.h>
 #include <asm/apic.h>
 #include "mach_reboot.h"
+#include <linux/reboot_fixups.h>
 
 /*
  * Power off function, if any
@@ -348,6 +349,7 @@
 		/* rebooting needs to touch the page at absolute addr 0 */
 		*((unsigned short *)__va(0x472)) = reboot_mode;
 		for (;;) {
+			mach_reboot_fixups(); /* for board specific fixups */
 			mach_reboot();
 			/* That didn't work - force a triple fault.. */
 			__asm__ __volatile__("lidt %0": :"m" (no_idt));
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
new file mode 100644
index 0000000..1b183b3
--- /dev/null
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -0,0 +1,56 @@
+/*
+ * linux/arch/i386/kernel/reboot_fixups.c
+ *
+ * This is a good place to put board specific reboot fixups.
+ *
+ * List of supported fixups:
+ * geode-gx1/cs5530a - Jaya Kumar <jayalk@intworks.biz>
+ *
+ */
+
+#include <asm/delay.h>
+#include <linux/pci.h>
+
+static void cs5530a_warm_reset(struct pci_dev *dev)
+{
+	/* writing 1 to the reset control register, 0x44 causes the
+	cs5530a to perform a system warm reset */
+	pci_write_config_byte(dev, 0x44, 0x1);
+	udelay(50); /* shouldn't get here but be safe and spin-a-while */
+	return;
+}
+
+struct device_fixup {
+	unsigned int vendor;
+	unsigned int device;
+	void (*reboot_fixup)(struct pci_dev *);
+};
+
+static struct device_fixup fixups_table[] = {
+{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
+};
+
+/*
+ * we see if any fixup is available for our current hardware. if there
+ * is a fixup, we call it and we expect to never return from it. if we
+ * do return, we keep looking and then eventually fall back to the
+ * standard mach_reboot on return.
+ */
+void mach_reboot_fixups(void)
+{
+	struct device_fixup *cur;
+	struct pci_dev *dev;
+	int i;
+
+	for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) {
+		cur = &(fixups_table[i]);
+		dev = pci_get_device(cur->vendor, cur->device, 0);
+		if (!dev)
+			continue;
+
+		cur->reboot_fixup(dev);
+	}
+
+	printk(KERN_WARNING "No reboot fixup found for your hardware\n");
+}
+
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index fd36d2f..cbea7ac 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1089,9 +1089,6 @@
 		}
 	}
 
-	if (nmi_watchdog == NMI_LOCAL_APIC)
-		check_nmi_watchdog();
-
 	smpboot_setup_io_apic();
 
 	setup_boot_APIC_clock();
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
new file mode 100644
index 0000000..6cd1ed3
--- /dev/null
+++ b/arch/i386/kernel/syscall_table.S
@@ -0,0 +1,291 @@
+.data
+ENTRY(sys_call_table)
+	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
+	.long sys_exit
+	.long sys_fork
+	.long sys_read
+	.long sys_write
+	.long sys_open		/* 5 */
+	.long sys_close
+	.long sys_waitpid
+	.long sys_creat
+	.long sys_link
+	.long sys_unlink	/* 10 */
+	.long sys_execve
+	.long sys_chdir
+	.long sys_time
+	.long sys_mknod
+	.long sys_chmod		/* 15 */
+	.long sys_lchown16
+	.long sys_ni_syscall	/* old break syscall holder */
+	.long sys_stat
+	.long sys_lseek
+	.long sys_getpid	/* 20 */
+	.long sys_mount
+	.long sys_oldumount
+	.long sys_setuid16
+	.long sys_getuid16
+	.long sys_stime		/* 25 */
+	.long sys_ptrace
+	.long sys_alarm
+	.long sys_fstat
+	.long sys_pause
+	.long sys_utime		/* 30 */
+	.long sys_ni_syscall	/* old stty syscall holder */
+	.long sys_ni_syscall	/* old gtty syscall holder */
+	.long sys_access
+	.long sys_nice
+	.long sys_ni_syscall	/* 35 - old ftime syscall holder */
+	.long sys_sync
+	.long sys_kill
+	.long sys_rename
+	.long sys_mkdir
+	.long sys_rmdir		/* 40 */
+	.long sys_dup
+	.long sys_pipe
+	.long sys_times
+	.long sys_ni_syscall	/* old prof syscall holder */
+	.long sys_brk		/* 45 */
+	.long sys_setgid16
+	.long sys_getgid16
+	.long sys_signal
+	.long sys_geteuid16
+	.long sys_getegid16	/* 50 */
+	.long sys_acct
+	.long sys_umount	/* recycled never used phys() */
+	.long sys_ni_syscall	/* old lock syscall holder */
+	.long sys_ioctl
+	.long sys_fcntl		/* 55 */
+	.long sys_ni_syscall	/* old mpx syscall holder */
+	.long sys_setpgid
+	.long sys_ni_syscall	/* old ulimit syscall holder */
+	.long sys_olduname
+	.long sys_umask		/* 60 */
+	.long sys_chroot
+	.long sys_ustat
+	.long sys_dup2
+	.long sys_getppid
+	.long sys_getpgrp	/* 65 */
+	.long sys_setsid
+	.long sys_sigaction
+	.long sys_sgetmask
+	.long sys_ssetmask
+	.long sys_setreuid16	/* 70 */
+	.long sys_setregid16
+	.long sys_sigsuspend
+	.long sys_sigpending
+	.long sys_sethostname
+	.long sys_setrlimit	/* 75 */
+	.long sys_old_getrlimit
+	.long sys_getrusage
+	.long sys_gettimeofday
+	.long sys_settimeofday
+	.long sys_getgroups16	/* 80 */
+	.long sys_setgroups16
+	.long old_select
+	.long sys_symlink
+	.long sys_lstat
+	.long sys_readlink	/* 85 */
+	.long sys_uselib
+	.long sys_swapon
+	.long sys_reboot
+	.long old_readdir
+	.long old_mmap		/* 90 */
+	.long sys_munmap
+	.long sys_truncate
+	.long sys_ftruncate
+	.long sys_fchmod
+	.long sys_fchown16	/* 95 */
+	.long sys_getpriority
+	.long sys_setpriority
+	.long sys_ni_syscall	/* old profil syscall holder */
+	.long sys_statfs
+	.long sys_fstatfs	/* 100 */
+	.long sys_ioperm
+	.long sys_socketcall
+	.long sys_syslog
+	.long sys_setitimer
+	.long sys_getitimer	/* 105 */
+	.long sys_newstat
+	.long sys_newlstat
+	.long sys_newfstat
+	.long sys_uname
+	.long sys_iopl		/* 110 */
+	.long sys_vhangup
+	.long sys_ni_syscall	/* old "idle" system call */
+	.long sys_vm86old
+	.long sys_wait4
+	.long sys_swapoff	/* 115 */
+	.long sys_sysinfo
+	.long sys_ipc
+	.long sys_fsync
+	.long sys_sigreturn
+	.long sys_clone		/* 120 */
+	.long sys_setdomainname
+	.long sys_newuname
+	.long sys_modify_ldt
+	.long sys_adjtimex
+	.long sys_mprotect	/* 125 */
+	.long sys_sigprocmask
+	.long sys_ni_syscall	/* old "create_module" */
+	.long sys_init_module
+	.long sys_delete_module
+	.long sys_ni_syscall	/* 130:	old "get_kernel_syms" */
+	.long sys_quotactl
+	.long sys_getpgid
+	.long sys_fchdir
+	.long sys_bdflush
+	.long sys_sysfs		/* 135 */
+	.long sys_personality
+	.long sys_ni_syscall	/* reserved for afs_syscall */
+	.long sys_setfsuid16
+	.long sys_setfsgid16
+	.long sys_llseek	/* 140 */
+	.long sys_getdents
+	.long sys_select
+	.long sys_flock
+	.long sys_msync
+	.long sys_readv		/* 145 */
+	.long sys_writev
+	.long sys_getsid
+	.long sys_fdatasync
+	.long sys_sysctl
+	.long sys_mlock		/* 150 */
+	.long sys_munlock
+	.long sys_mlockall
+	.long sys_munlockall
+	.long sys_sched_setparam
+	.long sys_sched_getparam   /* 155 */
+	.long sys_sched_setscheduler
+	.long sys_sched_getscheduler
+	.long sys_sched_yield
+	.long sys_sched_get_priority_max
+	.long sys_sched_get_priority_min  /* 160 */
+	.long sys_sched_rr_get_interval
+	.long sys_nanosleep
+	.long sys_mremap
+	.long sys_setresuid16
+	.long sys_getresuid16	/* 165 */
+	.long sys_vm86
+	.long sys_ni_syscall	/* Old sys_query_module */
+	.long sys_poll
+	.long sys_nfsservctl
+	.long sys_setresgid16	/* 170 */
+	.long sys_getresgid16
+	.long sys_prctl
+	.long sys_rt_sigreturn
+	.long sys_rt_sigaction
+	.long sys_rt_sigprocmask	/* 175 */
+	.long sys_rt_sigpending
+	.long sys_rt_sigtimedwait
+	.long sys_rt_sigqueueinfo
+	.long sys_rt_sigsuspend
+	.long sys_pread64	/* 180 */
+	.long sys_pwrite64
+	.long sys_chown16
+	.long sys_getcwd
+	.long sys_capget
+	.long sys_capset	/* 185 */
+	.long sys_sigaltstack
+	.long sys_sendfile
+	.long sys_ni_syscall	/* reserved for streams1 */
+	.long sys_ni_syscall	/* reserved for streams2 */
+	.long sys_vfork		/* 190 */
+	.long sys_getrlimit
+	.long sys_mmap2
+	.long sys_truncate64
+	.long sys_ftruncate64
+	.long sys_stat64	/* 195 */
+	.long sys_lstat64
+	.long sys_fstat64
+	.long sys_lchown
+	.long sys_getuid
+	.long sys_getgid	/* 200 */
+	.long sys_geteuid
+	.long sys_getegid
+	.long sys_setreuid
+	.long sys_setregid
+	.long sys_getgroups	/* 205 */
+	.long sys_setgroups
+	.long sys_fchown
+	.long sys_setresuid
+	.long sys_getresuid
+	.long sys_setresgid	/* 210 */
+	.long sys_getresgid
+	.long sys_chown
+	.long sys_setuid
+	.long sys_setgid
+	.long sys_setfsuid	/* 215 */
+	.long sys_setfsgid
+	.long sys_pivot_root
+	.long sys_mincore
+	.long sys_madvise
+	.long sys_getdents64	/* 220 */
+	.long sys_fcntl64
+	.long sys_ni_syscall	/* reserved for TUX */
+	.long sys_ni_syscall
+	.long sys_gettid
+	.long sys_readahead	/* 225 */
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr
+	.long sys_getxattr
+	.long sys_lgetxattr	/* 230 */
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr
+	.long sys_flistxattr
+	.long sys_removexattr	/* 235 */
+	.long sys_lremovexattr
+	.long sys_fremovexattr
+	.long sys_tkill
+	.long sys_sendfile64
+	.long sys_futex		/* 240 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_set_thread_area
+	.long sys_get_thread_area
+	.long sys_io_setup	/* 245 */
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel
+	.long sys_fadvise64	/* 250 */
+	.long sys_ni_syscall
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl	/* 255 */
+	.long sys_epoll_wait
+ 	.long sys_remap_file_pages
+ 	.long sys_set_tid_address
+ 	.long sys_timer_create
+ 	.long sys_timer_settime		/* 260 */
+ 	.long sys_timer_gettime
+ 	.long sys_timer_getoverrun
+ 	.long sys_timer_delete
+ 	.long sys_clock_settime
+ 	.long sys_clock_gettime		/* 265 */
+ 	.long sys_clock_getres
+ 	.long sys_clock_nanosleep
+	.long sys_statfs64
+	.long sys_fstatfs64
+	.long sys_tgkill	/* 270 */
+	.long sys_utimes
+ 	.long sys_fadvise64_64
+	.long sys_ni_syscall	/* sys_vserver */
+	.long sys_mbind
+	.long sys_get_mempolicy
+	.long sys_set_mempolicy
+	.long sys_mq_open
+	.long sys_mq_unlink
+	.long sys_mq_timedsend
+	.long sys_mq_timedreceive	/* 280 */
+	.long sys_mq_notify
+	.long sys_mq_getsetattr
+	.long sys_ni_syscall		/* reserved for kexec */
+	.long sys_waitid
+	.long sys_ni_syscall		/* 285 */ /* available */
+	.long sys_add_key
+	.long sys_request_key
+	.long sys_keyctl
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 4d75b37..a0dcb7c 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -441,7 +441,7 @@
 	set_normalized_timespec(&wall_to_monotonic,
 		-xtime.tv_sec, -xtime.tv_nsec);
 
-	if (hpet_enable() >= 0) {
+	if ((hpet_enable() >= 0) && hpet_use_timer) {
 		printk("Using HPET for base-timer\n");
 	}
 
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 244a31b..10a0cbb 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -26,6 +26,7 @@
 static unsigned long hpet_period;	/* fsecs / HPET clock */
 unsigned long hpet_tick;		/* hpet clks count per tick */
 unsigned long hpet_address;		/* hpet memory map physical address */
+int hpet_use_timer;
 
 static int use_hpet; 		/* can be used for runtime check of hpet */
 static int boot_hpet_disable; 	/* boottime override for HPET timer */
@@ -73,27 +74,30 @@
 	hpet_writel(0, HPET_COUNTER);
 	hpet_writel(0, HPET_COUNTER + 4);
 
-	/*
-	 * Set up timer 0, as periodic with first interrupt to happen at
-	 * hpet_tick, and period also hpet_tick.
-	 */
-	cfg = hpet_readl(HPET_T0_CFG);
-	cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-	       HPET_TN_SETVAL | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T0_CFG);
+	if (hpet_use_timer) {
+		/*
+		 * Set up timer 0, as periodic with first interrupt to happen at
+		 * hpet_tick, and period also hpet_tick.
+		 */
+		cfg = hpet_readl(HPET_T0_CFG);
+		cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+		       HPET_TN_SETVAL | HPET_TN_32BIT;
+		hpet_writel(cfg, HPET_T0_CFG);
 
-	/*
-	 * The first write after writing TN_SETVAL to the config register sets
-	 * the counter value, the second write sets the threshold.
-	 */
-	hpet_writel(tick, HPET_T0_CMP);
-	hpet_writel(tick, HPET_T0_CMP);
-
+		/*
+		 * The first write after writing TN_SETVAL to the config register sets
+		 * the counter value, the second write sets the threshold.
+		 */
+		hpet_writel(tick, HPET_T0_CMP);
+		hpet_writel(tick, HPET_T0_CMP);
+	}
 	/*
  	 * Go!
  	 */
 	cfg = hpet_readl(HPET_CFG);
-	cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+	if (hpet_use_timer)
+		cfg |= HPET_CFG_LEGACY;
+	cfg |= HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 
 	return 0;
@@ -128,12 +132,11 @@
 	 * However, we can do with one timer otherwise using the
 	 * the single HPET timer for system time.
 	 */
-	if (
 #ifdef CONFIG_HPET_EMULATE_RTC
-		!(id & HPET_ID_NUMBER) ||
-#endif
-	    !(id & HPET_ID_LEGSUP))
+	if (!(id & HPET_ID_NUMBER))
 		return -1;
+#endif
+
 
 	hpet_period = hpet_readl(HPET_PERIOD);
 	if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD))
@@ -152,6 +155,8 @@
 	if (hpet_tick_rem > (hpet_period >> 1))
 		hpet_tick++; /* rounding the result */
 
+	hpet_use_timer = id & HPET_ID_LEGSUP;
+
 	if (hpet_timer_stop_set_go(hpet_tick))
 		return -1;
 
@@ -202,7 +207,8 @@
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
-	wait_timer_tick = wait_hpet_tick;
+	if (hpet_use_timer)
+		wait_timer_tick = wait_hpet_tick;
 #endif
 	return 0;
 }
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index 713134e..f778f47 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -79,7 +79,7 @@
 
 	eax = hpet_readl(HPET_COUNTER);
 	eax -= hpet_last;	/* hpet delta */
-
+	eax = min(hpet_tick, eax);
 	/*
          * Time offset = (hpet delta) * ( usecs per HPET clock )
 	 *             = (hpet delta) * ( usecs per tick / HPET clocks per tick)
@@ -105,9 +105,12 @@
 	last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
 	rdtsc(last_tsc_low, last_tsc_high);
 
-	offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-	if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) {
-		int lost_ticks = (offset - hpet_last) / hpet_tick;
+	if (hpet_use_timer)
+		offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
+	else
+		offset = hpet_readl(HPET_COUNTER);
+	if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) {
+		int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1;
 		jiffies_64 += lost_ticks;
 	}
 	hpet_last = offset;
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index a685994..7926d96 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -477,7 +477,7 @@
 	if (cpu_has_tsc) {
 		unsigned long tsc_quotient;
 #ifdef CONFIG_HPET_TIMER
-		if (is_hpet_enabled()){
+		if (is_hpet_enabled() && hpet_use_timer) {
 			unsigned long result, remain;
 			printk("Using TSC for gettimeofday\n");
 			tsc_quotient = calibrate_tsc_hpet(NULL);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 6c0e383..00c6341 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -451,6 +451,7 @@
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
 
 fastcall void do_general_protection(struct pt_regs * regs, long error_code)
 {
@@ -642,16 +643,15 @@
 }
 
 #ifdef CONFIG_KPROBES
-fastcall int do_int3(struct pt_regs *regs, long error_code)
+fastcall void do_int3(struct pt_regs *regs, long error_code)
 {
 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
 			== NOTIFY_STOP)
-		return 1;
+		return;
 	/* This is an interrupt gate, because kprobes wants interrupts
 	disabled.  Normal trap handlers don't. */
 	restore_interrupts(regs);
 	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
-	return 0;
 }
 #endif
 
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 2f3d52d..ec0f68c 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -222,7 +222,7 @@
 			goto out;
 		case VM86_PLUS_INSTALL_CHECK:
 			/* NOTE: on old vm86 stuff this will return the error
-			   from verify_area(), because the subfunction is
+			   from access_ok(), because the subfunction is
 			   interpreted as (invalid) address to vm86_struct.
 			   So the installation check works.
 			 */
@@ -294,8 +294,8 @@
  */
 	info->regs32->eax = 0;
 	tsk->thread.saved_esp0 = tsk->thread.esp0;
-	asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
-	asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
+	asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs));
+	asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs));
 
 	tss = &per_cpu(init_tss, get_cpu());
 	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -717,12 +717,12 @@
 	irqbits |= irq_bit;
 	if (vm86_irqs[intno].sig)
 		send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
-	spin_unlock_irqrestore(&irqbits_lock, flags);
 	/*
 	 * IRQ will be re-enabled when user asks for the irq (whether
 	 * polling or as a result of the signal)
 	 */
-	disable_irq(intno);
+	disable_irq_nosync(intno);
+	spin_unlock_irqrestore(&irqbits_lock, flags);
 	return IRQ_HANDLED;
 
 out:
@@ -754,17 +754,20 @@
 {
 	int bit;
 	unsigned long flags;
+	int ret = 0;
 	
 	if (invalid_vm86_irq(irqnumber)) return 0;
 	if (vm86_irqs[irqnumber].tsk != current) return 0;
 	spin_lock_irqsave(&irqbits_lock, flags);	
 	bit = irqbits & (1 << irqnumber);
 	irqbits &= ~bit;
+	if (bit) {
+		enable_irq(irqnumber);
+		ret = 1;
+	}
+
 	spin_unlock_irqrestore(&irqbits_lock, flags);	
-	if (!bit)
-		return 0;
-	enable_irq(irqnumber);
-	return 1;
+	return ret;
 }
 
 
diff --git a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c
index b2e462a..c58d0c1 100644
--- a/arch/i386/oprofile/nmi_timer_int.c
+++ b/arch/i386/oprofile/nmi_timer_int.c
@@ -36,7 +36,7 @@
 {
 	enable_timer_nmi_watchdog();
 	unset_nmi_callback();
-	synchronize_kernel();
+	synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
 
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index e07589d..d6598da 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -495,6 +495,8 @@
 		case PCI_DEVICE_ID_INTEL_ICH6_1:
 		case PCI_DEVICE_ID_INTEL_ICH7_0:
 		case PCI_DEVICE_ID_INTEL_ICH7_1:
+		case PCI_DEVICE_ID_INTEL_ICH7_30:
+		case PCI_DEVICE_ID_INTEL_ICH7_31:
 		case PCI_DEVICE_ID_INTEL_ESB2_0:
 			r->name = "PIIX/ICH";
 			r->get = pirq_piix_get;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 33fcb20..3ad2c4a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -46,6 +46,10 @@
 	bool
 	default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+	bool
+	default y
+
 choice
 	prompt "System type"
 	default IA64_GENERIC
@@ -217,6 +221,16 @@
 	  If you are compiling a kernel that will run under SGI's IA-64
 	  simulator (Medusa) then say Y, otherwise say N.
 
+config IA64_SGI_SN_XP
+	tristate "Support communication between SGI SSIs"
+	depends on MSPEC
+	help
+	  An SGI machine can be divided into multiple Single System
+	  Images which act independently of each other and have
+	  hardware based memory protection from the others.  Enabling
+	  this feature will allow for direct communication between SSIs
+	  based on a network adapter and DMA messaging.
+
 config FORCE_MAX_ZONEORDER
 	int
 	default "18"
@@ -261,6 +275,15 @@
 	  can be controlled through /sys/devices/system/cpu/cpu#.
 	  Say N if you want to disable CPU hotplug.
 
+config SCHED_SMT
+	bool "SMT scheduler support"
+	depends on SMP
+	default off
+	help
+	  Improves the CPU scheduler's decision making when dealing with
+	  Intel IA64 chips with MultiThreading at a cost of slightly increased
+	  overhead in some places. If unsure say N here.
+
 config PREEMPT
 	bool "Preemptible Kernel"
         help
@@ -329,7 +352,7 @@
 
 config PM
 	bool "Power Management support"
-	depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB
+	depends on !IA64_HP_SIM
 	default y
 	help
 	  "Power Management" means that parts of your computer are shut
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index bfeb952..6ff7107 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -574,6 +574,8 @@
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
 CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
 
 #
 # Serial drivers
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 99830e8..9086b78 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Sat Jan 22 11:17:02 2005
+# Linux kernel version: 2.6.12-rc3
+# Tue May  3 15:55:04 2005
 #
 
 #
@@ -10,6 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -21,24 +22,27 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=20
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -85,6 +89,7 @@
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_HOTPLUG_CPU=y
+# CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
@@ -135,6 +140,7 @@
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCI Hotplug Support
@@ -152,10 +158,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # Device Drivers
 #
 
@@ -195,9 +197,10 @@
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -313,7 +316,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -325,7 +327,6 @@
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 CONFIG_SCSI_QLOGIC_FC=y
 # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
 CONFIG_SCSI_QLOGIC_1280=y
@@ -336,6 +337,7 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -358,6 +360,7 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -386,7 +389,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -446,7 +448,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -484,7 +485,6 @@
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=m
 CONFIG_E100=m
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -566,25 +566,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461X is not set
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -602,6 +583,24 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461X is not set
+CONFIG_SOUND_GAMEPORT=m
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -615,6 +614,8 @@
 # CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
 # CONFIG_STALDRV is not set
 
 #
@@ -635,6 +636,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -670,6 +672,12 @@
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -705,7 +713,6 @@
 #
 CONFIG_VGA_CONSOLE=y
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -715,6 +722,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -726,8 +735,6 @@
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -736,6 +743,8 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
 
@@ -751,12 +760,11 @@
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
@@ -800,6 +808,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
 
 #
 # USB port drivers
@@ -824,6 +833,7 @@
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -867,7 +877,12 @@
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
@@ -945,7 +960,7 @@
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1042,8 +1057,10 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1077,6 +1094,7 @@
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 017c9ab..b8db6e3 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1,9 +1,9 @@
 /*
 **  IA64 System Bus Adapter (SBA) I/O MMU manager
 **
-**	(c) Copyright 2002-2004 Alex Williamson
+**	(c) Copyright 2002-2005 Alex Williamson
 **	(c) Copyright 2002-2003 Grant Grundler
-**	(c) Copyright 2002-2004 Hewlett-Packard Company
+**	(c) Copyright 2002-2005 Hewlett-Packard Company
 **
 **	Portions (c) 2000 Grant Grundler (from parisc I/O MMU code)
 **	Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
@@ -459,21 +459,32 @@
  * sba_search_bitmap - find free space in IO PDIR resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @bits_wanted: number of entries we need.
+ * @use_hint: use res_hint to indicate where to start looking
  *
  * Find consecutive free bits in resource bitmap.
  * Each bit represents one entry in the IO Pdir.
  * Cool perf optimization: search for log2(size) bits at a time.
  */
 static SBA_INLINE unsigned long
-sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
+sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
 {
-	unsigned long *res_ptr = ioc->res_hint;
+	unsigned long *res_ptr;
 	unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
-	unsigned long pide = ~0UL;
+	unsigned long flags, pide = ~0UL;
 
 	ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
 	ASSERT(res_ptr < res_end);
 
+	spin_lock_irqsave(&ioc->res_lock, flags);
+
+	/* Allow caller to force a search through the entire resource space */
+	if (likely(use_hint)) {
+		res_ptr = ioc->res_hint;
+	} else {
+		res_ptr = (ulong *)ioc->res_map;
+		ioc->res_bitshift = 0;
+	}
+
 	/*
 	 * N.B.  REO/Grande defect AR2305 can cause TLB fetch timeouts
 	 * if a TLB entry is purged while in use.  sba_mark_invalid()
@@ -570,10 +581,12 @@
 	prefetch(ioc->res_map);
 	ioc->res_hint = (unsigned long *) ioc->res_map;
 	ioc->res_bitshift = 0;
+	spin_unlock_irqrestore(&ioc->res_lock, flags);
 	return (pide);
 
 found_it:
 	ioc->res_hint = res_ptr;
+	spin_unlock_irqrestore(&ioc->res_lock, flags);
 	return (pide);
 }
 
@@ -594,36 +607,36 @@
 	unsigned long itc_start;
 #endif
 	unsigned long pide;
-	unsigned long flags;
 
 	ASSERT(pages_needed);
 	ASSERT(0 == (size & ~iovp_mask));
 
-	spin_lock_irqsave(&ioc->res_lock, flags);
-
 #ifdef PDIR_SEARCH_TIMING
 	itc_start = ia64_get_itc();
 #endif
 	/*
 	** "seek and ye shall find"...praying never hurts either...
 	*/
-	pide = sba_search_bitmap(ioc, pages_needed);
+	pide = sba_search_bitmap(ioc, pages_needed, 1);
 	if (unlikely(pide >= (ioc->res_size << 3))) {
-		pide = sba_search_bitmap(ioc, pages_needed);
+		pide = sba_search_bitmap(ioc, pages_needed, 0);
 		if (unlikely(pide >= (ioc->res_size << 3))) {
 #if DELAYED_RESOURCE_CNT > 0
+			unsigned long flags;
+
 			/*
 			** With delayed resource freeing, we can give this one more shot.  We're
 			** getting close to being in trouble here, so do what we can to make this
 			** one count.
 			*/
-			spin_lock(&ioc->saved_lock);
+			spin_lock_irqsave(&ioc->saved_lock, flags);
 			if (ioc->saved_cnt > 0) {
 				struct sba_dma_pair *d;
 				int cnt = ioc->saved_cnt;
 
-				d = &(ioc->saved[ioc->saved_cnt]);
+				d = &(ioc->saved[ioc->saved_cnt - 1]);
 
+				spin_lock(&ioc->res_lock);
 				while (cnt--) {
 					sba_mark_invalid(ioc, d->iova, d->size);
 					sba_free_range(ioc, d->iova, d->size);
@@ -631,10 +644,11 @@
 				}
 				ioc->saved_cnt = 0;
 				READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
+				spin_unlock(&ioc->res_lock);
 			}
-			spin_unlock(&ioc->saved_lock);
+			spin_unlock_irqrestore(&ioc->saved_lock, flags);
 
-			pide = sba_search_bitmap(ioc, pages_needed);
+			pide = sba_search_bitmap(ioc, pages_needed, 0);
 			if (unlikely(pide >= (ioc->res_size << 3)))
 				panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
 				      ioc->ioc_hpa);
@@ -664,8 +678,6 @@
 		(uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
 		ioc->res_bitshift );
 
-	spin_unlock_irqrestore(&ioc->res_lock, flags);
-
 	return (pide);
 }
 
@@ -950,6 +962,30 @@
 	return SBA_IOVA(ioc, iovp, offset);
 }
 
+#ifdef ENABLE_MARK_CLEAN
+static SBA_INLINE void
+sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
+{
+	u32	iovp = (u32) SBA_IOVP(ioc,iova);
+	int	off = PDIR_INDEX(iovp);
+	void	*addr;
+
+	if (size <= iovp_size) {
+		addr = phys_to_virt(ioc->pdir_base[off] &
+		                    ~0xE000000000000FFFULL);
+		mark_clean(addr, size);
+	} else {
+		do {
+			addr = phys_to_virt(ioc->pdir_base[off] &
+			                    ~0xE000000000000FFFULL);
+			mark_clean(addr, min(size, iovp_size));
+			off++;
+			size -= iovp_size;
+		} while (size > 0);
+	}
+}
+#endif
+
 /**
  * sba_unmap_single - unmap one IOVA and free resources
  * @dev: instance of PCI owned by the driver that's asking.
@@ -995,6 +1031,10 @@
 	size += offset;
 	size = ROUNDUP(size, iovp_size);
 
+#ifdef ENABLE_MARK_CLEAN
+	if (dir == DMA_FROM_DEVICE)
+		sba_mark_clean(ioc, iova, size);
+#endif
 
 #if DELAYED_RESOURCE_CNT > 0
 	spin_lock_irqsave(&ioc->saved_lock, flags);
@@ -1021,30 +1061,6 @@
 	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif /* DELAYED_RESOURCE_CNT == 0 */
-#ifdef ENABLE_MARK_CLEAN
-	if (dir == DMA_FROM_DEVICE) {
-		u32 iovp = (u32) SBA_IOVP(ioc,iova);
-		int off = PDIR_INDEX(iovp);
-		void *addr;
-
-		if (size <= iovp_size) {
-			addr = phys_to_virt(ioc->pdir_base[off] &
-					    ~0xE000000000000FFFULL);
-			mark_clean(addr, size);
-		} else {
-			size_t byte_cnt = size;
-
-			do {
-				addr = phys_to_virt(ioc->pdir_base[off] &
-				                    ~0xE000000000000FFFULL);
-				mark_clean(addr, min(byte_cnt, iovp_size));
-				off++;
-				byte_cnt -= iovp_size;
-
-			   } while (byte_cnt > 0);
-		}
-	}
-#endif
 }
 
 
@@ -1928,43 +1944,17 @@
 static void __init
 sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 {
-	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-	union acpi_object *obj;
-	acpi_handle phandle;
 	unsigned int node;
+	int pxm;
 
 	ioc->node = MAX_NUMNODES;
 
-	/*
-	 * Check for a _PXM on this node first.  We don't typically see
-	 * one here, so we'll end up getting it from the parent.
-	 */
-	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) {
-		if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
-			return;
+	pxm = acpi_get_pxm(handle);
 
-		/* Reset the acpi buffer */
-		buffer.length = ACPI_ALLOCATE_BUFFER;
-		buffer.pointer = NULL;
-
-		if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL,
-		                                      &buffer)))
-			return;
-	}
-
-	if (!buffer.length || !buffer.pointer)
+	if (pxm < 0)
 		return;
 
-	obj = buffer.pointer;
-
-	if (obj->type != ACPI_TYPE_INTEGER ||
-	    obj->integer.value >= MAX_PXM_DOMAINS) {
-		acpi_os_free(buffer.pointer);
-		return;
-	}
-
-	node = pxm_to_nid_map[obj->integer.value];
-	acpi_os_free(buffer.pointer);
+	node = pxm_to_nid_map[pxm];
 
 	if (node >= MAX_NUMNODES || !node_online(node))
 		return;
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 19b02ad..ebb89be 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -460,10 +460,9 @@
 	sigset_t oldset, set;
 
 	scr->scratch_unat = 0;	/* avoid leaking kernel bits to user level */
-	memset(&set, 0, sizeof(&set));
+	memset(&set, 0, sizeof(set));
 
-	if (memcpy(&set.sig, &sset->sig, sigsetsize))
-		return -EFAULT;
+	memcpy(&set.sig, &sset->sig, sigsetsize);
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index a8e99c5..72dfd9e 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -779,7 +779,7 @@
 	union acpi_object *obj;
 	struct acpi_table_iosapic *iosapic;
 	unsigned int gsi_base;
-	int node;
+	int pxm, node;
 
 	/* Only care about objects w/ a method that returns the MADT */
 	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
@@ -805,29 +805,16 @@
 	gsi_base = iosapic->global_irq_base;
 
 	acpi_os_free(buffer.pointer);
-	buffer.length = ACPI_ALLOCATE_BUFFER;
-	buffer.pointer = NULL;
 
 	/*
-	 * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell
+	 * OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell
 	 * us which node to associate this with.
 	 */
-	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer)))
+	pxm = acpi_get_pxm(handle);
+	if (pxm < 0)
 		return AE_OK;
 
-	if (!buffer.length || !buffer.pointer)
-		return AE_OK;
-
-	obj = buffer.pointer;
-
-	if (obj->type != ACPI_TYPE_INTEGER ||
-	    obj->integer.value >= MAX_PXM_DOMAINS) {
-		acpi_os_free(buffer.pointer);
-		return AE_OK;
-	}
-
-	node = pxm_to_nid_map[obj->integer.value];
-	acpi_os_free(buffer.pointer);
+	node = pxm_to_nid_map[pxm];
 
 	if (node >= MAX_NUMNODES || !node_online(node) ||
 	    cpus_empty(node_to_cpumask(node)))
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0272c01..81c45d4 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -728,12 +728,8 @@
 	mov f8=f0		// clear f8
 	;;
 	ld8 r30=[r2],16		// M0|1 load cr.ifs
-	mov.m ar.ssd=r0		// M2 clear ar.ssd
-	cmp.eq p9,p0=r0,r0	// set p9 to indicate that we should restore cr.ifs
-	;;
 	ld8 r25=[r3],16		// M0|1 load ar.unat
-	mov.m ar.csd=r0		// M2 clear ar.csd
-	mov r22=r0		// clear r22
+	cmp.eq p9,p0=r0,r0	// set p9 to indicate that we should restore cr.ifs
 	;;
 	ld8 r26=[r2],PT(B0)-PT(AR_PFS)	// M0|1 load ar.pfs
 (pKStk)	mov r22=psr		// M2 read PSR now that interrupts are disabled
@@ -756,11 +752,15 @@
 	mov f7=f0		// clear f7
 	;;
 	ld8.fill r12=[r2]	// restore r12 (sp)
+	mov.m ar.ssd=r0		// M2 clear ar.ssd
+	mov r22=r0		// clear r22
+
 	ld8.fill r15=[r3]	// restore r15
+(pUStk) st1 [r14]=r17
 	addl r3=THIS_CPU(ia64_phys_stacked_size_p8),r0
 	;;
-(pUStk)	ld4 r3=[r3]		// r3 = cpu_data->phys_stacked_size_p8
-(pUStk) st1 [r14]=r17
+(pUStk)	ld4 r17=[r3]		// r17 = cpu_data->phys_stacked_size_p8
+	mov.m ar.csd=r0		// M2 clear ar.csd
 	mov b6=r18		// I0  restore b6
 	;;
 	mov r14=r0		// clear r14
@@ -782,7 +782,7 @@
 	st8.spill [r2]=r8	// store return value in slot for r8 and set unat bit
 	.mem.offset 8,0
 	st8.spill [r3]=r0	// clear error indication in slot for r10 and set unat bit
-END(ia64_ret_from_ia32_execve_syscall)
+END(ia64_ret_from_ia32_execve)
 	// fall through
 #endif /* CONFIG_IA32_SUPPORT */
 GLOBAL_ENTRY(ia64_leave_kernel)
@@ -1417,7 +1417,7 @@
 	data8 sys_msgrcv
 	data8 sys_msgctl
 	data8 sys_shmget
-	data8 ia64_shmat
+	data8 sys_shmat
 	data8 sys_shmdt				// 1115
 	data8 sys_shmctl
 	data8 sys_syslog
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 0d8650f..4f3cdef 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -611,8 +611,10 @@
 	movl r2=ia64_ret_from_syscall
 	;;
 	mov rp=r2				// set the real return addr
-	tbit.z p8,p0=r3,TIF_SYSCALL_TRACE
+	and r3=_TIF_SYSCALL_TRACEAUDIT,r3
 	;;
+	cmp.eq p8,p0=r3,r0
+
 (p10)	br.cond.spnt.many ia64_ret_from_syscall	// p10==true means out registers are more than 8
 (p8)	br.call.sptk.many b6=b6		// ignore this return addr
 	br.cond.sptk ia64_trace_syscall
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 105c7fe..8d3a929 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -15,6 +15,8 @@
  * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
  * Copyright (C) 2002 Fenghua Yu <fenghua.yu@intel.com>
  *   -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2.
+ * Copyright (C) 2004 Ashok Raj <ashok.raj@intel.com>
+ *   Support for CPU Hotplug
  */
 
 #include <linux/config.h>
@@ -29,6 +31,139 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <asm/mca_asm.h>
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define SAL_PSR_BITS_TO_SET				\
+	(IA64_PSR_AC | IA64_PSR_BN | IA64_PSR_MFH | IA64_PSR_MFL)
+
+#define SAVE_FROM_REG(src, ptr, dest)	\
+	mov dest=src;;						\
+	st8 [ptr]=dest,0x08
+
+#define RESTORE_REG(reg, ptr, _tmp)		\
+	ld8 _tmp=[ptr],0x08;;				\
+	mov reg=_tmp
+
+#define SAVE_BREAK_REGS(ptr, _idx, _breg, _dest)\
+	mov ar.lc=IA64_NUM_DBG_REGS-1;; 			\
+	mov _idx=0;; 								\
+1: 												\
+	SAVE_FROM_REG(_breg[_idx], ptr, _dest);;	\
+	add _idx=1,_idx;;							\
+	br.cloop.sptk.many 1b
+
+#define RESTORE_BREAK_REGS(ptr, _idx, _breg, _tmp, _lbl)\
+	mov ar.lc=IA64_NUM_DBG_REGS-1;;			\
+	mov _idx=0;;							\
+_lbl:  RESTORE_REG(_breg[_idx], ptr, _tmp);;	\
+	add _idx=1, _idx;;						\
+	br.cloop.sptk.many _lbl
+
+#define SAVE_ONE_RR(num, _reg, _tmp) \
+	movl _tmp=(num<<61);;	\
+	mov _reg=rr[_tmp]
+
+#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \
+	SAVE_ONE_RR(0,_r0, _tmp);; \
+	SAVE_ONE_RR(1,_r1, _tmp);; \
+	SAVE_ONE_RR(2,_r2, _tmp);; \
+	SAVE_ONE_RR(3,_r3, _tmp);; \
+	SAVE_ONE_RR(4,_r4, _tmp);; \
+	SAVE_ONE_RR(5,_r5, _tmp);; \
+	SAVE_ONE_RR(6,_r6, _tmp);; \
+	SAVE_ONE_RR(7,_r7, _tmp);;
+
+#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \
+	st8 [ptr]=_r0, 8;; \
+	st8 [ptr]=_r1, 8;; \
+	st8 [ptr]=_r2, 8;; \
+	st8 [ptr]=_r3, 8;; \
+	st8 [ptr]=_r4, 8;; \
+	st8 [ptr]=_r5, 8;; \
+	st8 [ptr]=_r6, 8;; \
+	st8 [ptr]=_r7, 8;;
+
+#define RESTORE_REGION_REGS(ptr, _idx1, _idx2, _tmp) \
+	mov		ar.lc=0x08-1;;						\
+	movl	_idx1=0x00;;						\
+RestRR:											\
+	dep.z	_idx2=_idx1,61,3;;					\
+	ld8		_tmp=[ptr],8;;						\
+	mov		rr[_idx2]=_tmp;;					\
+	srlz.d;;									\
+	add		_idx1=1,_idx1;;						\
+	br.cloop.sptk.few	RestRR
+
+#define SET_AREA_FOR_BOOTING_CPU(reg1, reg2) \
+	movl reg1=sal_state_for_booting_cpu;;	\
+	ld8 reg2=[reg1];;
+
+/*
+ * Adjust region registers saved before starting to save
+ * break regs and rest of the states that need to be preserved.
+ */
+#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(_reg1,_reg2,_pred)  \
+	SAVE_FROM_REG(b0,_reg1,_reg2);;						\
+	SAVE_FROM_REG(b1,_reg1,_reg2);;						\
+	SAVE_FROM_REG(b2,_reg1,_reg2);;						\
+	SAVE_FROM_REG(b3,_reg1,_reg2);;						\
+	SAVE_FROM_REG(b4,_reg1,_reg2);;						\
+	SAVE_FROM_REG(b5,_reg1,_reg2);;						\
+	st8 [_reg1]=r1,0x08;;								\
+	st8 [_reg1]=r12,0x08;;								\
+	st8 [_reg1]=r13,0x08;;								\
+	SAVE_FROM_REG(ar.fpsr,_reg1,_reg2);;				\
+	SAVE_FROM_REG(ar.pfs,_reg1,_reg2);;					\
+	SAVE_FROM_REG(ar.rnat,_reg1,_reg2);;				\
+	SAVE_FROM_REG(ar.unat,_reg1,_reg2);;				\
+	SAVE_FROM_REG(ar.bspstore,_reg1,_reg2);;			\
+	SAVE_FROM_REG(cr.dcr,_reg1,_reg2);;					\
+	SAVE_FROM_REG(cr.iva,_reg1,_reg2);;					\
+	SAVE_FROM_REG(cr.pta,_reg1,_reg2);;					\
+	SAVE_FROM_REG(cr.itv,_reg1,_reg2);;					\
+	SAVE_FROM_REG(cr.pmv,_reg1,_reg2);;					\
+	SAVE_FROM_REG(cr.cmcv,_reg1,_reg2);;				\
+	SAVE_FROM_REG(cr.lrr0,_reg1,_reg2);;				\
+	SAVE_FROM_REG(cr.lrr1,_reg1,_reg2);;				\
+	st8 [_reg1]=r4,0x08;;								\
+	st8 [_reg1]=r5,0x08;;								\
+	st8 [_reg1]=r6,0x08;;								\
+	st8 [_reg1]=r7,0x08;;								\
+	st8 [_reg1]=_pred,0x08;;							\
+	SAVE_FROM_REG(ar.lc, _reg1, _reg2);;				\
+	stf.spill.nta [_reg1]=f2,16;;						\
+	stf.spill.nta [_reg1]=f3,16;;						\
+	stf.spill.nta [_reg1]=f4,16;;						\
+	stf.spill.nta [_reg1]=f5,16;;						\
+	stf.spill.nta [_reg1]=f16,16;;						\
+	stf.spill.nta [_reg1]=f17,16;;						\
+	stf.spill.nta [_reg1]=f18,16;;						\
+	stf.spill.nta [_reg1]=f19,16;;						\
+	stf.spill.nta [_reg1]=f20,16;;						\
+	stf.spill.nta [_reg1]=f21,16;;						\
+	stf.spill.nta [_reg1]=f22,16;;						\
+	stf.spill.nta [_reg1]=f23,16;;						\
+	stf.spill.nta [_reg1]=f24,16;;						\
+	stf.spill.nta [_reg1]=f25,16;;						\
+	stf.spill.nta [_reg1]=f26,16;;						\
+	stf.spill.nta [_reg1]=f27,16;;						\
+	stf.spill.nta [_reg1]=f28,16;;						\
+	stf.spill.nta [_reg1]=f29,16;;						\
+	stf.spill.nta [_reg1]=f30,16;;						\
+	stf.spill.nta [_reg1]=f31,16;;
+
+#else
+#define SET_AREA_FOR_BOOTING_CPU(a1, a2)
+#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(a1,a2, a3)
+#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7)
+#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7)
+#endif
+
+#define SET_ONE_RR(num, pgsize, _tmp1, _tmp2, vhpt) \
+	movl _tmp1=(num << 61);;	\
+	mov _tmp2=((ia64_rid(IA64_REGION_ID_KERNEL, (num<<61)) << 8) | (pgsize << 2) | vhpt);; \
+	mov rr[_tmp1]=_tmp2
 
 	.section __special_page_section,"ax"
 
@@ -64,6 +199,12 @@
 	srlz.i
 	;;
 	/*
+	 * Save the region registers, predicate before they get clobbered
+	 */
+	SAVE_REGION_REGS(r2, r8,r9,r10,r11,r12,r13,r14,r15);
+	mov r25=pr;;
+
+	/*
 	 * Initialize kernel region registers:
 	 *	rr[0]: VHPT enabled, page size = PAGE_SHIFT
 	 *	rr[1]: VHPT enabled, page size = PAGE_SHIFT
@@ -76,32 +217,14 @@
 	 * We initialize all of them to prevent inadvertently assuming
 	 * something about the state of address translation early in boot.
 	 */
-	mov r6=((ia64_rid(IA64_REGION_ID_KERNEL, (0<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
-	movl r7=(0<<61)
-	mov r8=((ia64_rid(IA64_REGION_ID_KERNEL, (1<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
-	movl r9=(1<<61)
-	mov r10=((ia64_rid(IA64_REGION_ID_KERNEL, (2<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
-	movl r11=(2<<61)
-	mov r12=((ia64_rid(IA64_REGION_ID_KERNEL, (3<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
-	movl r13=(3<<61)
-	mov r14=((ia64_rid(IA64_REGION_ID_KERNEL, (4<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
-	movl r15=(4<<61)
-	mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, (5<<61)) << 8) | (PAGE_SHIFT << 2) | 1)
-	movl r17=(5<<61)
-	mov r18=((ia64_rid(IA64_REGION_ID_KERNEL, (6<<61)) << 8) | (IA64_GRANULE_SHIFT << 2))
-	movl r19=(6<<61)
-	mov r20=((ia64_rid(IA64_REGION_ID_KERNEL, (7<<61)) << 8) | (IA64_GRANULE_SHIFT << 2))
-	movl r21=(7<<61)
-	;;
-	mov rr[r7]=r6
-	mov rr[r9]=r8
-	mov rr[r11]=r10
-	mov rr[r13]=r12
-	mov rr[r15]=r14
-	mov rr[r17]=r16
-	mov rr[r19]=r18
-	mov rr[r21]=r20
-	;;
+	SET_ONE_RR(0, PAGE_SHIFT, r2, r16, 1);;
+	SET_ONE_RR(1, PAGE_SHIFT, r2, r16, 1);;
+	SET_ONE_RR(2, PAGE_SHIFT, r2, r16, 1);;
+	SET_ONE_RR(3, PAGE_SHIFT, r2, r16, 1);;
+	SET_ONE_RR(4, PAGE_SHIFT, r2, r16, 1);;
+	SET_ONE_RR(5, PAGE_SHIFT, r2, r16, 1);;
+	SET_ONE_RR(6, IA64_GRANULE_SHIFT, r2, r16, 0);;
+	SET_ONE_RR(7, IA64_GRANULE_SHIFT, r2, r16, 0);;
 	/*
 	 * Now pin mappings into the TLB for kernel text and data
 	 */
@@ -142,6 +265,12 @@
 	;;
 1:	// now we are in virtual mode
 
+	SET_AREA_FOR_BOOTING_CPU(r2, r16);
+
+	STORE_REGION_REGS(r16, r8,r9,r10,r11,r12,r13,r14,r15);
+	SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(r16,r17,r25)
+	;;
+
 	// set IVT entry point---can't access I/O ports without it
 	movl r3=ia64_ivt
 	;;
@@ -211,12 +340,13 @@
 	mov IA64_KR(CURRENT_STACK)=r16
 	mov r13=r2
 	/*
-	 * Reserve space at the top of the stack for "struct pt_regs".  Kernel threads
-	 * don't store interesting values in that structure, but the space still needs
-	 * to be there because time-critical stuff such as the context switching can
-	 * be implemented more efficiently (for example, __switch_to()
+	 * Reserve space at the top of the stack for "struct pt_regs".  Kernel
+	 * threads don't store interesting values in that structure, but the space
+	 * still needs to be there because time-critical stuff such as the context
+	 * switching can be implemented more efficiently (for example, __switch_to()
 	 * always sets the psr.dfh bit of the task it is switching to).
 	 */
+
 	addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE-16,r2
 	addl r2=IA64_RBS_OFFSET,r2	// initialize the RSE
 	mov ar.rsc=0		// place RSE in enforced lazy mode
@@ -993,4 +1123,98 @@
 
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+GLOBAL_ENTRY(ia64_jump_to_sal)
+	alloc r16=ar.pfs,1,0,0,0;;
+	rsm psr.i  | psr.ic
+{
+	flushrs
+	srlz.i
+}
+	tpa r25=in0
+	movl r18=tlb_purge_done;;
+	DATA_VA_TO_PA(r18);;
+	mov b1=r18 	// Return location
+	movl r18=ia64_do_tlb_purge;;
+	DATA_VA_TO_PA(r18);;
+	mov b2=r18 	// doing tlb_flush work
+	mov ar.rsc=0  // Put RSE  in enforced lazy, LE mode
+	movl r17=1f;;
+	DATA_VA_TO_PA(r17);;
+	mov cr.iip=r17
+	movl r16=SAL_PSR_BITS_TO_SET;;
+	mov cr.ipsr=r16
+	mov cr.ifs=r0;;
+	rfi;;
+1:
+	/*
+	 * Invalidate all TLB data/inst
+	 */
+	br.sptk.many b2;; // jump to tlb purge code
+
+tlb_purge_done:
+	RESTORE_REGION_REGS(r25, r17,r18,r19);;
+	RESTORE_REG(b0, r25, r17);;
+	RESTORE_REG(b1, r25, r17);;
+	RESTORE_REG(b2, r25, r17);;
+	RESTORE_REG(b3, r25, r17);;
+	RESTORE_REG(b4, r25, r17);;
+	RESTORE_REG(b5, r25, r17);;
+	ld8 r1=[r25],0x08;;
+	ld8 r12=[r25],0x08;;
+	ld8 r13=[r25],0x08;;
+	RESTORE_REG(ar.fpsr, r25, r17);;
+	RESTORE_REG(ar.pfs, r25, r17);;
+	RESTORE_REG(ar.rnat, r25, r17);;
+	RESTORE_REG(ar.unat, r25, r17);;
+	RESTORE_REG(ar.bspstore, r25, r17);;
+	RESTORE_REG(cr.dcr, r25, r17);;
+	RESTORE_REG(cr.iva, r25, r17);;
+	RESTORE_REG(cr.pta, r25, r17);;
+	RESTORE_REG(cr.itv, r25, r17);;
+	RESTORE_REG(cr.pmv, r25, r17);;
+	RESTORE_REG(cr.cmcv, r25, r17);;
+	RESTORE_REG(cr.lrr0, r25, r17);;
+	RESTORE_REG(cr.lrr1, r25, r17);;
+	ld8 r4=[r25],0x08;;
+	ld8 r5=[r25],0x08;;
+	ld8 r6=[r25],0x08;;
+	ld8 r7=[r25],0x08;;
+	ld8 r17=[r25],0x08;;
+	mov pr=r17,-1;;
+	RESTORE_REG(ar.lc, r25, r17);;
+	/*
+	 * Now Restore floating point regs
+	 */
+	ldf.fill.nta f2=[r25],16;;
+	ldf.fill.nta f3=[r25],16;;
+	ldf.fill.nta f4=[r25],16;;
+	ldf.fill.nta f5=[r25],16;;
+	ldf.fill.nta f16=[r25],16;;
+	ldf.fill.nta f17=[r25],16;;
+	ldf.fill.nta f18=[r25],16;;
+	ldf.fill.nta f19=[r25],16;;
+	ldf.fill.nta f20=[r25],16;;
+	ldf.fill.nta f21=[r25],16;;
+	ldf.fill.nta f22=[r25],16;;
+	ldf.fill.nta f23=[r25],16;;
+	ldf.fill.nta f24=[r25],16;;
+	ldf.fill.nta f25=[r25],16;;
+	ldf.fill.nta f26=[r25],16;;
+	ldf.fill.nta f27=[r25],16;;
+	ldf.fill.nta f28=[r25],16;;
+	ldf.fill.nta f29=[r25],16;;
+	ldf.fill.nta f30=[r25],16;;
+	ldf.fill.nta f31=[r25],16;;
+
+	/*
+	 * Now that we have done all the register restores
+	 * we are now ready for the big DIVE to SAL Land
+	 */
+	ssm psr.ic;;
+	srlz.d;;
+	br.ret.sptk.many b0;;
+END(ia64_jump_to_sal)
+#endif /* CONFIG_HOTPLUG_CPU */
+
 #endif /* CONFIG_SMP */
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index c15be5c..88b0143 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -79,6 +79,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
+#include <linux/bootmem.h>
 
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
@@ -98,19 +99,30 @@
 #define DBG(fmt...)
 #endif
 
+#define NR_PREALLOCATE_RTE_ENTRIES	(PAGE_SIZE / sizeof(struct iosapic_rte_info))
+#define RTE_PREALLOCATED	(1)
+
 static DEFINE_SPINLOCK(iosapic_lock);
 
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
 
-static struct iosapic_intr_info {
+struct iosapic_rte_info {
+	struct list_head rte_list;	/* node in list of RTEs sharing the same vector */
 	char __iomem	*addr;		/* base address of IOSAPIC */
-	u32		low32;		/* current value of low word of Redirection table entry */
 	unsigned int	gsi_base;	/* first GSI assigned to this IOSAPIC */
-	char		rte_index;	/* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
+	char		rte_index;	/* IOSAPIC RTE index */
+	int		refcnt;		/* reference counter */
+	unsigned int	flags;		/* flags */
+} ____cacheline_aligned;
+
+static struct iosapic_intr_info {
+	struct list_head rtes;		/* RTEs using this vector (empty => not an IOSAPIC interrupt) */
+	int		count;		/* # of RTEs that shares this vector */
+	u32		low32;		/* current value of low word of Redirection table entry */
+	unsigned int	dest;		/* destination CPU physical ID */
 	unsigned char	dmode	: 3;	/* delivery mode (see iosapic.h) */
 	unsigned char 	polarity: 1;	/* interrupt polarity (see iosapic.h) */
 	unsigned char	trigger	: 1;	/* trigger mode (see iosapic.h) */
-	int		refcnt;		/* reference counter */
 } iosapic_intr_info[IA64_NUM_VECTORS];
 
 static struct iosapic {
@@ -126,6 +138,8 @@
 
 static unsigned char pcat_compat __initdata;	/* 8259 compatibility flag */
 
+static int iosapic_kmalloc_ok;
+static LIST_HEAD(free_rte_list);
 
 /*
  * Find an IOSAPIC associated with a GSI
@@ -147,10 +161,12 @@
 _gsi_to_vector (unsigned int gsi)
 {
 	struct iosapic_intr_info *info;
+	struct iosapic_rte_info *rte;
 
 	for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info)
-		if (info->gsi_base + info->rte_index == gsi)
-			return info - iosapic_intr_info;
+		list_for_each_entry(rte, &info->rtes, rte_list)
+			if (rte->gsi_base + rte->rte_index == gsi)
+				return info - iosapic_intr_info;
 	return -1;
 }
 
@@ -167,33 +183,52 @@
 int
 gsi_to_irq (unsigned int gsi)
 {
+	unsigned long flags;
+	int irq;
 	/*
 	 * XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
 	 * numbers...
 	 */
-	return _gsi_to_vector(gsi);
+	spin_lock_irqsave(&iosapic_lock, flags);
+	{
+		irq = _gsi_to_vector(gsi);
+	}
+	spin_unlock_irqrestore(&iosapic_lock, flags);
+
+	return irq;
+}
+
+static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned int vec)
+{
+	struct iosapic_rte_info *rte;
+
+	list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
+		if (rte->gsi_base + rte->rte_index == gsi)
+			return rte;
+	return NULL;
 }
 
 static void
-set_rte (unsigned int vector, unsigned int dest, int mask)
+set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
 {
 	unsigned long pol, trigger, dmode;
 	u32 low32, high32;
 	char __iomem *addr;
 	int rte_index;
 	char redir;
+	struct iosapic_rte_info *rte;
 
 	DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
 
-	rte_index = iosapic_intr_info[vector].rte_index;
-	if (rte_index < 0)
+	rte = gsi_vector_to_rte(gsi, vector);
+	if (!rte)
 		return;		/* not an IOSAPIC interrupt */
 
-	addr    = iosapic_intr_info[vector].addr;
+	rte_index = rte->rte_index;
+	addr	= rte->addr;
 	pol     = iosapic_intr_info[vector].polarity;
 	trigger = iosapic_intr_info[vector].trigger;
 	dmode   = iosapic_intr_info[vector].dmode;
-	vector &= (~IA64_IRQ_REDIRECTED);
 
 	redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
 
@@ -221,6 +256,7 @@
 	iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
 	iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
 	iosapic_intr_info[vector].low32 = low32;
+	iosapic_intr_info[vector].dest = dest;
 }
 
 static void
@@ -237,18 +273,20 @@
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
+	struct iosapic_rte_info *rte;
 
-	addr = iosapic_intr_info[vec].addr;
-	rte_index = iosapic_intr_info[vec].rte_index;
-
-	if (rte_index < 0)
+	if (list_empty(&iosapic_intr_info[vec].rtes))
 		return;			/* not an IOSAPIC interrupt! */
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
 		/* set only the mask bit */
 		low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
-		iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+			addr = rte->addr;
+			rte_index = rte->rte_index;
+			iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -261,16 +299,19 @@
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
+	struct iosapic_rte_info *rte;
 
-	addr = iosapic_intr_info[vec].addr;
-	rte_index = iosapic_intr_info[vec].rte_index;
-	if (rte_index < 0)
+	if (list_empty(&iosapic_intr_info[vec].rtes))
 		return;			/* not an IOSAPIC interrupt! */
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
 		low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
-		iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+			addr = rte->addr;
+			rte_index = rte->rte_index;
+			iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -286,6 +327,7 @@
 	char __iomem *addr;
 	int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
 	ia64_vector vec;
+	struct iosapic_rte_info *rte;
 
 	irq &= (~IA64_IRQ_REDIRECTED);
 	vec = irq_to_vector(irq);
@@ -295,10 +337,7 @@
 
 	dest = cpu_physical_id(first_cpu(mask));
 
-	rte_index = iosapic_intr_info[vec].rte_index;
-	addr = iosapic_intr_info[vec].addr;
-
-	if (rte_index < 0)
+	if (list_empty(&iosapic_intr_info[vec].rtes))
 		return;			/* not an IOSAPIC interrupt */
 
 	set_irq_affinity_info(irq, dest, redir);
@@ -318,8 +357,13 @@
 			low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
 
 		iosapic_intr_info[vec].low32 = low32;
-		iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
-		iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+		iosapic_intr_info[vec].dest = dest;
+		list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
+			addr = rte->addr;
+			rte_index = rte->rte_index;
+			iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
+			iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+		}
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 #endif
@@ -340,9 +384,11 @@
 iosapic_end_level_irq (unsigned int irq)
 {
 	ia64_vector vec = irq_to_vector(irq);
+	struct iosapic_rte_info *rte;
 
 	move_irq(irq);
-	iosapic_eoi(iosapic_intr_info[vec].addr, vec);
+	list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
+		iosapic_eoi(rte->addr, vec);
 }
 
 #define iosapic_shutdown_level_irq	mask_irq
@@ -422,6 +468,34 @@
 	return iosapic_read(addr, IOSAPIC_VERSION);
 }
 
+static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long pol)
+{
+	int i, vector = -1, min_count = -1;
+	struct iosapic_intr_info *info;
+
+	/*
+	 * shared vectors for edge-triggered interrupts are not
+	 * supported yet
+	 */
+	if (trigger == IOSAPIC_EDGE)
+		return -1;
+
+	for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) {
+		info = &iosapic_intr_info[i];
+		if (info->trigger == trigger && info->polarity == pol &&
+		    (info->dmode == IOSAPIC_FIXED || info->dmode == IOSAPIC_LOWEST_PRIORITY)) {
+			if (min_count == -1 || info->count < min_count) {
+				vector = i;
+				min_count = info->count;
+			}
+		}
+	}
+	if (vector < 0)
+		panic("%s: out of interrupt vectors!\n", __FUNCTION__);
+
+	return vector;
+}
+
 /*
  * if the given vector is already owned by other,
  *  assign a new vector for the other and make the vector available
@@ -431,19 +505,63 @@
 {
 	int new_vector;
 
-	if (iosapic_intr_info[vector].rte_index >= 0 || iosapic_intr_info[vector].addr
-	    || iosapic_intr_info[vector].gsi_base || iosapic_intr_info[vector].dmode
-	    || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger)
-	{
+	if (!list_empty(&iosapic_intr_info[vector].rtes)) {
 		new_vector = assign_irq_vector(AUTO_ASSIGN);
 		printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);
 		memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
 		       sizeof(struct iosapic_intr_info));
+		INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes);
+		list_move(iosapic_intr_info[vector].rtes.next, &iosapic_intr_info[new_vector].rtes);
 		memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
-		iosapic_intr_info[vector].rte_index = -1;
+		iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
+		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
 	}
 }
 
+static struct iosapic_rte_info *iosapic_alloc_rte (void)
+{
+	int i;
+	struct iosapic_rte_info *rte;
+	int preallocated = 0;
+
+	if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
+		rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * NR_PREALLOCATE_RTE_ENTRIES);
+		if (!rte)
+			return NULL;
+		for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
+			list_add(&rte->rte_list, &free_rte_list);
+	}
+
+	if (!list_empty(&free_rte_list)) {
+		rte = list_entry(free_rte_list.next, struct iosapic_rte_info, rte_list);
+		list_del(&rte->rte_list);
+		preallocated++;
+	} else {
+		rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
+		if (!rte)
+			return NULL;
+	}
+
+	memset(rte, 0, sizeof(struct iosapic_rte_info));
+	if (preallocated)
+		rte->flags |= RTE_PREALLOCATED;
+
+	return rte;
+}
+
+static void iosapic_free_rte (struct iosapic_rte_info *rte)
+{
+	if (rte->flags & RTE_PREALLOCATED)
+		list_add_tail(&rte->rte_list, &free_rte_list);
+	else
+		kfree(rte);
+}
+
+static inline int vector_is_shared (int vector)
+{
+	return (iosapic_intr_info[vector].count > 1);
+}
+
 static void
 register_intr (unsigned int gsi, int vector, unsigned char delivery,
 	       unsigned long polarity, unsigned long trigger)
@@ -454,6 +572,7 @@
 	int index;
 	unsigned long gsi_base;
 	void __iomem *iosapic_address;
+	struct iosapic_rte_info *rte;
 
 	index = find_iosapic(gsi);
 	if (index < 0) {
@@ -464,14 +583,33 @@
 	iosapic_address = iosapic_lists[index].addr;
 	gsi_base = iosapic_lists[index].gsi_base;
 
-	rte_index = gsi - gsi_base;
-	iosapic_intr_info[vector].rte_index = rte_index;
+	rte = gsi_vector_to_rte(gsi, vector);
+	if (!rte) {
+		rte = iosapic_alloc_rte();
+		if (!rte) {
+			printk(KERN_WARNING "%s: cannot allocate memory\n", __FUNCTION__);
+			return;
+		}
+
+		rte_index = gsi - gsi_base;
+		rte->rte_index	= rte_index;
+		rte->addr	= iosapic_address;
+		rte->gsi_base	= gsi_base;
+		rte->refcnt++;
+		list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);
+		iosapic_intr_info[vector].count++;
+	}
+	else if (vector_is_shared(vector)) {
+		struct iosapic_intr_info *info = &iosapic_intr_info[vector];
+		if (info->trigger != trigger || info->polarity != polarity) {
+			printk (KERN_WARNING "%s: cannot override the interrupt\n", __FUNCTION__);
+			return;
+		}
+	}
+
 	iosapic_intr_info[vector].polarity = polarity;
 	iosapic_intr_info[vector].dmode    = delivery;
-	iosapic_intr_info[vector].addr     = iosapic_address;
-	iosapic_intr_info[vector].gsi_base = gsi_base;
 	iosapic_intr_info[vector].trigger  = trigger;
-	iosapic_intr_info[vector].refcnt++;
 
 	if (trigger == IOSAPIC_EDGE)
 		irq_type = &irq_type_iosapic_edge;
@@ -494,6 +632,13 @@
 	static int cpu = -1;
 
 	/*
+	 * In case of vector shared by multiple RTEs, all RTEs that
+	 * share the vector need to use the same destination CPU.
+	 */
+	if (!list_empty(&iosapic_intr_info[vector].rtes))
+		return iosapic_intr_info[vector].dest;
+
+	/*
 	 * If the platform supports redirection via XTP, let it
 	 * distribute interrupts.
 	 */
@@ -565,10 +710,12 @@
 iosapic_register_intr (unsigned int gsi,
 		       unsigned long polarity, unsigned long trigger)
 {
-	int vector;
+	int vector, mask = 1;
 	unsigned int dest;
 	unsigned long flags;
-
+	struct iosapic_rte_info *rte;
+	u32 low32;
+again:
 	/*
 	 * If this GSI has already been registered (i.e., it's a
 	 * shared interrupt, or we lost a race to register it),
@@ -578,20 +725,46 @@
 	{
 		vector = gsi_to_vector(gsi);
 		if (vector > 0) {
-			iosapic_intr_info[vector].refcnt++;
+			rte = gsi_vector_to_rte(gsi, vector);
+			rte->refcnt++;
 			spin_unlock_irqrestore(&iosapic_lock, flags);
 			return vector;
 		}
-
-		vector = assign_irq_vector(AUTO_ASSIGN);
-		dest = get_target_cpu(gsi, vector);
-		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-			polarity, trigger);
-
-		set_rte(vector, dest, 1);
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 
+	/* If vector is running out, we try to find a sharable vector */
+	vector = assign_irq_vector_nopanic(AUTO_ASSIGN);
+	if (vector < 0)
+		vector = iosapic_find_sharable_vector(trigger, polarity);
+
+	spin_lock_irqsave(&irq_descp(vector)->lock, flags);
+	spin_lock(&iosapic_lock);
+	{
+		if (gsi_to_vector(gsi) > 0) {
+			if (list_empty(&iosapic_intr_info[vector].rtes))
+				free_irq_vector(vector);
+			spin_unlock(&iosapic_lock);
+			spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+			goto again;
+		}
+
+		dest = get_target_cpu(gsi, vector);
+		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
+			      polarity, trigger);
+
+		/*
+		 * If the vector is shared and already unmasked for
+		 * other interrupt sources, don't mask it.
+		 */
+		low32 = iosapic_intr_info[vector].low32;
+		if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK))
+			mask = 0;
+		set_rte(gsi, vector, dest, mask);
+	}
+	spin_unlock(&iosapic_lock);
+	spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+
 	printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
 	       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
 	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
@@ -607,8 +780,10 @@
 	unsigned long flags;
 	int irq, vector;
 	irq_desc_t *idesc;
-	int rte_index;
+	u32 low32;
 	unsigned long trigger, polarity;
+	unsigned int dest;
+	struct iosapic_rte_info *rte;
 
 	/*
 	 * If the irq associated with the gsi is not found,
@@ -627,54 +802,56 @@
 	spin_lock_irqsave(&idesc->lock, flags);
 	spin_lock(&iosapic_lock);
 	{
-		rte_index = iosapic_intr_info[vector].rte_index;
-		if (rte_index < 0) {
-			spin_unlock(&iosapic_lock);
-			spin_unlock_irqrestore(&idesc->lock, flags);
+		if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {
 			printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);
 			WARN_ON(1);
-			return;
+			goto out;
 		}
 
-		if (--iosapic_intr_info[vector].refcnt > 0) {
-			spin_unlock(&iosapic_lock);
-			spin_unlock_irqrestore(&idesc->lock, flags);
-			return;
-		}
+		if (--rte->refcnt > 0)
+			goto out;
 
-		/*
-		 * If interrupt handlers still exist on the irq
-		 * associated with the gsi, don't unregister the
-		 * interrupt.
-		 */
-		if (idesc->action) {
-			iosapic_intr_info[vector].refcnt++;
-			spin_unlock(&iosapic_lock);
-			spin_unlock_irqrestore(&idesc->lock, flags);
-			printk(KERN_WARNING "Cannot unregister GSI. IRQ %u is still in use.\n", irq);
-			return;
-		}
+		/* Mask the interrupt */
+		low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
+		iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32);
 
-		/* Clear the interrupt controller descriptor. */
-		idesc->handler = &no_irq_type;
+		/* Remove the rte entry from the list */
+		list_del(&rte->rte_list);
+		iosapic_intr_info[vector].count--;
+		iosapic_free_rte(rte);
 
-		trigger  = iosapic_intr_info[vector].trigger;
+		trigger	 = iosapic_intr_info[vector].trigger;
 		polarity = iosapic_intr_info[vector].polarity;
+		dest     = iosapic_intr_info[vector].dest;
+		printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
+		       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
+		       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+		       cpu_logical_id(dest), dest, vector);
 
-		/* Clear the interrupt information. */
-		memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
-		iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
+		if (list_empty(&iosapic_intr_info[vector].rtes)) {
+			/* Sanity check */
+			BUG_ON(iosapic_intr_info[vector].count);
+
+			/* Clear the interrupt controller descriptor */
+			idesc->handler = &no_irq_type;
+
+			/* Clear the interrupt information */
+			memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
+			iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;
+			INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
+
+			if (idesc->action) {
+				printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq);
+				WARN_ON(1);
+			}
+
+			/* Free the interrupt vector */
+			free_irq_vector(vector);
+		}
 	}
+ out:
 	spin_unlock(&iosapic_lock);
 	spin_unlock_irqrestore(&idesc->lock, flags);
-
-	/* Free the interrupt vector */
-	free_irq_vector(vector);
-
-	printk(KERN_INFO "GSI %u (%s, %s) -> vector %d unregisterd.\n",
-	       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
-	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
-	       vector);
 }
 #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
 
@@ -724,7 +901,7 @@
 	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 	       cpu_logical_id(dest), dest, vector);
 
-	set_rte(vector, dest, mask);
+	set_rte(gsi, vector, dest, mask);
 	return vector;
 }
 
@@ -750,7 +927,7 @@
 	    polarity == IOSAPIC_POL_HIGH ? "high" : "low",
 	    cpu_logical_id(dest), dest, vector);
 
-	set_rte(vector, dest, 1);
+	set_rte(gsi, vector, dest, 1);
 }
 
 void __init
@@ -758,8 +935,10 @@
 {
 	int vector;
 
-	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
-		iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */
+	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {
+		iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
+		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);	/* mark as unused */
+	}
 
 	pcat_compat = system_pcat_compat;
 	if (pcat_compat) {
@@ -825,3 +1004,10 @@
 	return;
 }
 #endif
+
+static int __init iosapic_enable_kmalloc (void)
+{
+	iosapic_kmalloc_ok = 1;
+	return 0;
+}
+core_initcall (iosapic_enable_kmalloc);
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 5ba06eb..4fe60c7 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -63,20 +63,30 @@
 static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
 
 int
-assign_irq_vector (int irq)
+assign_irq_vector_nopanic (int irq)
 {
 	int pos, vector;
  again:
 	pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS);
 	vector = IA64_FIRST_DEVICE_VECTOR + pos;
 	if (vector > IA64_LAST_DEVICE_VECTOR)
-		/* XXX could look for sharable vectors instead of panic'ing... */
-		panic("assign_irq_vector: out of interrupt vectors!");
+		return -1;
 	if (test_and_set_bit(pos, ia64_vector_mask))
 		goto again;
 	return vector;
 }
 
+int
+assign_irq_vector (int irq)
+{
+	int vector = assign_irq_vector_nopanic(irq);
+
+	if (vector < 0)
+		panic("assign_irq_vector: out of interrupt vectors!");
+
+	return vector;
+}
+
 void
 free_irq_vector (int vector)
 {
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index cf3f8014..ef3fd72 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -110,46 +110,19 @@
 	.global ia64_os_mca_dispatch_end
 	.global ia64_sal_to_os_handoff_state
 	.global	ia64_os_to_sal_handoff_state
+	.global ia64_do_tlb_purge
 
 	.text
 	.align 16
 
-ia64_os_mca_dispatch:
+/*
+ * Just the TLB purge part is moved to a separate function
+ * so we can re-use the code for cpu hotplug code as well
+ * Caller should now setup b1, so we can branch once the
+ * tlb flush is complete.
+ */
 
-	// Serialize all MCA processing
-	mov	r3=1;;
-	LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
-ia64_os_mca_spin:
-	xchg8	r4=[r2],r3;;
-	cmp.ne	p6,p0=r4,r0
-(p6)	br ia64_os_mca_spin
-
-	// Save the SAL to OS MCA handoff state as defined
-	// by SAL SPEC 3.0
-	// NOTE : The order in which the state gets saved
-	//	  is dependent on the way the C-structure
-	//	  for ia64_mca_sal_to_os_state_t has been
-	//	  defined in include/asm/mca.h
-	SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
-	;;
-
-	// LOG PROCESSOR STATE INFO FROM HERE ON..
-begin_os_mca_dump:
-	br	ia64_os_mca_proc_state_dump;;
-
-ia64_os_mca_done_dump:
-
-	LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
-	;;
-	ld8 r18=[r16]		// Get processor state parameter on existing PALE_CHECK.
-	;;
-	tbit.nz p6,p7=r18,60
-(p7)	br.spnt done_tlb_purge_and_reload
-
-	// The following code purges TC and TR entries. Then reload all TC entries.
-	// Purge percpu data TC entries.
-begin_tlb_purge_and_reload:
-
+ia64_do_tlb_purge:
 #define O(member)	IA64_CPUINFO_##member##_OFFSET
 
 	GET_THIS_PADDR(r2, cpu_info)	// load phys addr of cpu_info into r2
@@ -230,6 +203,51 @@
 	;;
 	srlz.i
 	;;
+	// Now branch away to caller.
+	br.sptk.many b1
+	;;
+
+ia64_os_mca_dispatch:
+
+	// Serialize all MCA processing
+	mov	r3=1;;
+	LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
+ia64_os_mca_spin:
+	xchg8	r4=[r2],r3;;
+	cmp.ne	p6,p0=r4,r0
+(p6)	br ia64_os_mca_spin
+
+	// Save the SAL to OS MCA handoff state as defined
+	// by SAL SPEC 3.0
+	// NOTE : The order in which the state gets saved
+	//	  is dependent on the way the C-structure
+	//	  for ia64_mca_sal_to_os_state_t has been
+	//	  defined in include/asm/mca.h
+	SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
+	;;
+
+	// LOG PROCESSOR STATE INFO FROM HERE ON..
+begin_os_mca_dump:
+	br	ia64_os_mca_proc_state_dump;;
+
+ia64_os_mca_done_dump:
+
+	LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
+	;;
+	ld8 r18=[r16]		// Get processor state parameter on existing PALE_CHECK.
+	;;
+	tbit.nz p6,p7=r18,60
+(p7)	br.spnt done_tlb_purge_and_reload
+
+	// The following code purges TC and TR entries. Then reload all TC entries.
+	// Purge percpu data TC entries.
+begin_tlb_purge_and_reload:
+	movl r18=ia64_reload_tr;;
+	LOAD_PHYSICAL(p0,r18,ia64_reload_tr);;
+	mov b1=r18;;
+	br.sptk.many ia64_do_tlb_purge;;
+
+ia64_reload_tr:
 	// Finally reload the TR registers.
 	// 1. Reload DTR/ITR registers for kernel.
 	mov r18=KERNEL_TR_PAGE_SHIFT<<2
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index ab47817..abc0113 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -132,8 +132,7 @@
 	spin_unlock(&mca_bh_lock);
 
 	/* This process is about to be killed itself */
-	force_sig(SIGKILL, current);
-	schedule();
+	do_exit(SIGKILL);
 }
 
 /**
@@ -439,6 +438,7 @@
 			psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;
 			psr2->cpl = 0;
 			psr2->ri  = 0;
+			psr2->i  = 0;
 
 			return 1;
 		}
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index bcfa05a..2d7e021 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -10,6 +10,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/processor.h>
+#include <asm/ptrace.h>
 
 GLOBAL_ENTRY(mca_handler_bhhook)
 	invala						// clear RSE ?
@@ -20,12 +21,21 @@
 	;;						
 	alloc		r16=ar.pfs,0,2,1,0		// make a new frame
 	;;
+	mov		ar.rsc=0
+	;;
 	mov		r13=IA64_KR(CURRENT)		// current task pointer
 	;;
-	adds		r12=IA64_TASK_THREAD_KSP_OFFSET,r13
+	mov		r2=r13
 	;;
-	ld8		r12=[r12]			// stack pointer
+	addl		r22=IA64_RBS_OFFSET,r2
 	;;
+	mov		ar.bspstore=r22
+	;;
+	addl		sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
+	;;
+	adds		r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+	;;
+	st1		[r2]=r0				// clear current->thread.on_ustack flag
 	mov		loc0=r16
 	movl		loc1=mca_handler_bh		// recovery C function
 	;;
@@ -34,7 +44,9 @@
 	;;
 	mov		loc1=rp
 	;;
-	br.call.sptk.many    rp=b6			// not return ...
+	ssm		psr.i
+	;;
+	br.call.sptk.many    rp=b6			// does not return ...
 	;;
 	mov		ar.pfs=loc0
 	mov 		rp=loc1
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 71147be..71c1016 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -480,14 +480,6 @@
 #define PFM_CMD_ARG_MANY	-1 /* cannot be zero */
 
 typedef struct {
-	int	debug;		/* turn on/off debugging via syslog */
-	int	debug_ovfl;	/* turn on/off debug printk in overflow handler */
-	int	fastctxsw;	/* turn on/off fast (unsecure) ctxsw */
-	int	expert_mode;	/* turn on/off value checking */
-	int 	debug_pfm_read;
-} pfm_sysctl_t;
-
-typedef struct {
 	unsigned long pfm_spurious_ovfl_intr_count;	/* keep track of spurious ovfl interrupts */
 	unsigned long pfm_replay_ovfl_intr_count;	/* keep track of replayed ovfl interrupts */
 	unsigned long pfm_ovfl_intr_count; 		/* keep track of ovfl interrupts */
@@ -514,8 +506,8 @@
 static pmu_config_t		*pmu_conf;
 
 /* sysctl() controls */
-static pfm_sysctl_t pfm_sysctl;
-int pfm_debug_var;
+pfm_sysctl_t pfm_sysctl;
+EXPORT_SYMBOL(pfm_sysctl);
 
 static ctl_table pfm_ctl_table[]={
 	{1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,},
@@ -1273,6 +1265,8 @@
 }
 EXPORT_SYMBOL(pfm_unregister_buffer_fmt);
 
+extern void update_pal_halt_status(int);
+
 static int
 pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
 {
@@ -1319,6 +1313,11 @@
 		is_syswide,
 		cpu));
 
+	/*
+	 * disable default_idle() to go to PAL_HALT
+	 */
+	update_pal_halt_status(0);
+
 	UNLOCK_PFS(flags);
 
 	return 0;
@@ -1374,6 +1373,12 @@
 		is_syswide,
 		cpu));
 
+	/*
+	 * if possible, enable default_idle() to go into PAL_HALT
+	 */
+	if (pfm_sessions.pfs_task_sessions == 0 && pfm_sessions.pfs_sys_sessions == 0)
+		update_pal_halt_status(1);
+
 	UNLOCK_PFS(flags);
 
 	return 0;
@@ -1576,7 +1581,7 @@
 		goto abort_locked;
 	}
 
-	DPRINT(("[%d] fd=%d type=%d\n", current->pid, msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type));
+	DPRINT(("fd=%d type=%d\n", msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type));
 
 	ret = -EFAULT;
   	if(copy_to_user(buf, msg, sizeof(pfm_msg_t)) == 0) ret = sizeof(pfm_msg_t);
@@ -3695,8 +3700,6 @@
 
 	pfm_sysctl.debug = m == 0 ? 0 : 1;
 
-	pfm_debug_var = pfm_sysctl.debug;
-
 	printk(KERN_INFO "perfmon debugging %s (timing reset)\n", pfm_sysctl.debug ? "on" : "off");
 
 	if (m == 0) {
@@ -4212,7 +4215,7 @@
 		DPRINT(("cannot load to [%d], invalid ctx_state=%d\n",
 			req->load_pid,
 			ctx->ctx_state));
-		return -EINVAL;
+		return -EBUSY;
 	}
 
 	DPRINT(("load_pid [%d] using_dbreg=%d\n", req->load_pid, ctx->ctx_fl_using_dbreg));
@@ -4714,16 +4717,26 @@
 	if (task == current || ctx->ctx_fl_system) return 0;
 
 	/*
-	 * if context is UNLOADED we are safe to go
+	 * we are monitoring another thread
 	 */
-	if (state == PFM_CTX_UNLOADED) return 0;
-
-	/*
-	 * no command can operate on a zombie context
-	 */
-	if (state == PFM_CTX_ZOMBIE) {
-		DPRINT(("cmd %d state zombie cannot operate on context\n", cmd));
-		return -EINVAL;
+	switch(state) {
+		case PFM_CTX_UNLOADED:
+			/*
+			 * if context is UNLOADED we are safe to go
+			 */
+			return 0;
+		case PFM_CTX_ZOMBIE:
+			/*
+			 * no command can operate on a zombie context
+			 */
+			DPRINT(("cmd %d state zombie cannot operate on context\n", cmd));
+			return -EINVAL;
+		case PFM_CTX_MASKED:
+			/*
+			 * PMU state has been saved to software even though
+			 * the thread may still be running.
+			 */
+			if (cmd != PFM_UNLOAD_CONTEXT) return 0;
 	}
 
 	/*
@@ -4996,13 +5009,21 @@
 }
 
 static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds);
-
+ /*
+  * pfm_handle_work() can be called with interrupts enabled
+  * (TIF_NEED_RESCHED) or disabled. The down_interruptible
+  * call may sleep, therefore we must re-enable interrupts
+  * to avoid deadlocks. It is safe to do so because this function
+  * is called ONLY when returning to user level (PUStk=1), in which case
+  * there is no risk of kernel stack overflow due to deep
+  * interrupt nesting.
+  */
 void
 pfm_handle_work(void)
 {
 	pfm_context_t *ctx;
 	struct pt_regs *regs;
-	unsigned long flags;
+	unsigned long flags, dummy_flags;
 	unsigned long ovfl_regs;
 	unsigned int reason;
 	int ret;
@@ -5039,18 +5060,15 @@
 	//if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking;
 	if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking;
 
+	/*
+	 * restore interrupt mask to what it was on entry.
+	 * Could be enabled/diasbled.
+	 */
 	UNPROTECT_CTX(ctx, flags);
 
-	 /*
-	  * pfm_handle_work() is currently called with interrupts disabled.
-	  * The down_interruptible call may sleep, therefore we
-	  * must re-enable interrupts to avoid deadlocks. It is
-	  * safe to do so because this function is called ONLY
-	  * when returning to user level (PUStk=1), in which case
-	  * there is no risk of kernel stack overflow due to deep
-	  * interrupt nesting.
-	  */
-	BUG_ON(flags & IA64_PSR_I);
+	/*
+	 * force interrupt enable because of down_interruptible()
+	 */
 	local_irq_enable();
 
 	DPRINT(("before block sleeping\n"));
@@ -5064,12 +5082,12 @@
 	DPRINT(("after block sleeping ret=%d\n", ret));
 
 	/*
-	 * disable interrupts to restore state we had upon entering
-	 * this function
+	 * lock context and mask interrupts again
+	 * We save flags into a dummy because we may have
+	 * altered interrupts mask compared to entry in this
+	 * function.
 	 */
-	local_irq_disable();
-
-	PROTECT_CTX(ctx, flags);
+	PROTECT_CTX(ctx, dummy_flags);
 
 	/*
 	 * we need to read the ovfl_regs only after wake-up
@@ -5095,7 +5113,9 @@
 	ctx->ctx_ovfl_regs[0] = 0UL;
 
 nothing_to_do:
-
+	/*
+	 * restore flags as they were upon entry
+	 */
 	UNPROTECT_CTX(ctx, flags);
 }
 
diff --git a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c
index 965d290..344941d 100644
--- a/arch/ia64/kernel/perfmon_default_smpl.c
+++ b/arch/ia64/kernel/perfmon_default_smpl.c
@@ -20,24 +20,17 @@
 MODULE_DESCRIPTION("perfmon default sampling format");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "debug");
-
-MODULE_PARM(debug_ovfl, "i");
-MODULE_PARM_DESC(debug_ovfl, "debug ovfl");
-
-
 #define DEFAULT_DEBUG 1
 
 #ifdef DEFAULT_DEBUG
 #define DPRINT(a) \
 	do { \
-		if (unlikely(debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
+		if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
 	} while (0)
 
 #define DPRINT_ovfl(a) \
 	do { \
-		if (unlikely(debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
+		if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
 	} while (0)
 
 #else
@@ -45,8 +38,6 @@
 #define DPRINT_ovfl(a)
 #endif
 
-static int debug, debug_ovfl;
-
 static int
 default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data)
 {
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 9129338..ebb71f3 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1998-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * 04/11/17 Ashok Raj	<ashok.raj@intel.com> Added CPU Hotplug Support
  */
 #define __KERNEL_SYSCALLS__	/* see <asm/unistd.h> */
 #include <linux/config.h>
@@ -49,7 +50,7 @@
 #include "sigframe.h"
 
 void (*ia64_mark_idle)(int);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
 unsigned long boot_option_idle_override = 0;
 EXPORT_SYMBOL(boot_option_idle_override);
@@ -172,7 +173,9 @@
 		ia64_do_signal(oldset, scr, in_syscall);
 }
 
-static int pal_halt = 1;
+static int pal_halt        = 1;
+static int can_do_pal_halt = 1;
+
 static int __init nohalt_setup(char * str)
 {
 	pal_halt = 0;
@@ -180,16 +183,20 @@
 }
 __setup("nohalt", nohalt_setup);
 
+void
+update_pal_halt_status(int status)
+{
+	can_do_pal_halt = pal_halt && status;
+}
+
 /*
  * We use this if we don't have any better idle routine..
  */
 void
 default_idle (void)
 {
-	unsigned long pmu_active = ia64_getreg(_IA64_REG_PSR) & (IA64_PSR_PP | IA64_PSR_UP);
-
 	while (!need_resched())
-		if (pal_halt && !pmu_active)
+		if (can_do_pal_halt)
 			safe_halt();
 		else
 			cpu_relax();
@@ -200,27 +207,20 @@
 static inline void play_dead(void)
 {
 	extern void ia64_cpu_local_tick (void);
+	unsigned int this_cpu = smp_processor_id();
+
 	/* Ack it */
 	__get_cpu_var(cpu_state) = CPU_DEAD;
 
-	/* We shouldn't have to disable interrupts while dead, but
-	 * some interrupts just don't seem to go away, and this makes
-	 * it "work" for testing purposes. */
 	max_xtp();
 	local_irq_disable();
-	/* Death loop */
-	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
-		cpu_relax();
-
+	idle_task_exit();
+	ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
 	/*
-	 * Enable timer interrupts from now on
-	 * Not required if we put processor in SAL_BOOT_RENDEZ mode.
+	 * The above is a point of no-return, the processor is
+	 * expected to be in SAL loop now.
 	 */
-	local_flush_tlb_all();
-	cpu_set(smp_processor_id(), cpu_online_map);
-	wmb();
-	ia64_cpu_local_tick ();
-	local_irq_enable();
+	BUG();
 }
 #else
 static inline void play_dead(void)
@@ -229,20 +229,31 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-
 void cpu_idle_wait(void)
 {
-        int cpu;
-        cpumask_t map;
+	unsigned int cpu, this_cpu = get_cpu();
+	cpumask_t map;
 
-        for_each_online_cpu(cpu)
-                cpu_set(cpu, cpu_idle_map);
+	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+	put_cpu();
 
-        wmb();
-        do {
-                ssleep(1);
-                cpus_and(map, cpu_idle_map, cpu_online_map);
-        } while (!cpus_empty(map));
+	cpus_clear(map);
+	for_each_online_cpu(cpu) {
+		per_cpu(cpu_idle_state, cpu) = 1;
+		cpu_set(cpu, map);
+	}
+
+	__get_cpu_var(cpu_idle_state) = 0;
+
+	wmb();
+	do {
+		ssleep(1);
+		for_each_online_cpu(cpu) {
+			if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+				cpu_clear(cpu, map);
+		}
+		cpus_and(map, map, cpu_online_map);
+	} while (!cpus_empty(map));
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
@@ -250,7 +261,6 @@
 cpu_idle (void)
 {
 	void (*mark_idle)(int) = ia64_mark_idle;
-	int cpu = smp_processor_id();
 
 	/* endless idle loop with no priority at all */
 	while (1) {
@@ -261,12 +271,13 @@
 		while (!need_resched()) {
 			void (*idle)(void);
 
+			if (__get_cpu_var(cpu_idle_state))
+				__get_cpu_var(cpu_idle_state) = 0;
+
+			rmb();
 			if (mark_idle)
 				(*mark_idle)(1);
 
-			if (cpu_isset(cpu, cpu_idle_map))
-				cpu_clear(cpu, cpu_idle_map);
-			rmb();
 			idle = pm_idle;
 			if (!idle)
 				idle = default_idle;
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 55789fc..907464e 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -17,6 +17,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/signal.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -1481,7 +1482,7 @@
 	      case PTRACE_CONT:
 		/* restart after signal. */
 		ret = -EIO;
-		if (data > _NSIG)
+		if (!valid_signal(data))
 			goto out_tsk;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -1520,7 +1521,7 @@
 		/* let child execute for one instruction */
 	      case PTRACE_SINGLEBLOCK:
 		ret = -EIO;
-		if (data > _NSIG)
+		if (!valid_signal(data))
 			goto out_tsk;
 
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -1595,20 +1596,25 @@
 		     long arg4, long arg5, long arg6, long arg7,
 		     struct pt_regs regs)
 {
-	long syscall;
-
-	if (unlikely(current->audit_context)) {
-		if (IS_IA32_PROCESS(&regs))
-			syscall = regs.r1;
-		else
-			syscall = regs.r15;
-
-		audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3);
-	}
-
-	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	if (test_thread_flag(TIF_SYSCALL_TRACE) 
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace();
+
+	if (unlikely(current->audit_context)) {
+		long syscall;
+		int arch;
+
+		if (IS_IA32_PROCESS(&regs)) {
+			syscall = regs.r1;
+			arch = AUDIT_ARCH_I386;
+		} else {
+			syscall = regs.r15;
+			arch = AUDIT_ARCH_IA64;
+		}
+
+		audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);
+	}
+
 }
 
 /* "asmlinkage" so the input arguments are preserved... */
@@ -1619,7 +1625,7 @@
 		     struct pt_regs regs)
 {
 	if (unlikely(current->audit_context))
-		audit_syscall_exit(current, regs.r8);
+		audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE)
 	    && (current->ptrace & PT_PTRACED))
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index f05650c..b7e6b4c 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -4,10 +4,15 @@
  * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *	Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2000, 2004 Intel Corp
+ * 	Rohit Seth <rohit.seth@intel.com>
+ * 	Suresh Siddha <suresh.b.siddha@intel.com>
+ * 	Gordon Jin <gordon.jin@intel.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  *
+ * 12/26/04 S.Siddha, G.Jin, R.Seth
+ *			Add multi-threading and multi-core detection
  * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
  * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
  * 03/31/00 R.Seth	cpu_initialized and current->processor fixes
@@ -296,6 +301,34 @@
 #endif
 }
 
+#ifdef CONFIG_SMP
+static void
+check_for_logical_procs (void)
+{
+	pal_logical_to_physical_t info;
+	s64 status;
+
+	status = ia64_pal_logical_to_phys(0, &info);
+	if (status == -1) {
+		printk(KERN_INFO "No logical to physical processor mapping "
+		       "available\n");
+		return;
+	}
+	if (status) {
+		printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
+		       status);
+		return;
+	}
+	/*
+	 * Total number of siblings that BSP has.  Though not all of them 
+	 * may have booted successfully. The correct number of siblings 
+	 * booted is in info.overview_num_log.
+	 */
+	smp_num_siblings = info.overview_tpc;
+	smp_num_cpucores = info.overview_cpp;
+}
+#endif
+
 void __init
 setup_arch (char **cmdline_p)
 {
@@ -356,6 +389,19 @@
 
 #ifdef CONFIG_SMP
 	cpu_physical_id(0) = hard_smp_processor_id();
+
+	cpu_set(0, cpu_sibling_map[0]);
+	cpu_set(0, cpu_core_map[0]);
+
+	check_for_logical_procs();
+	if (smp_num_cpucores > 1)
+		printk(KERN_INFO
+		       "cpu package is Multi-Core capable: number of cores=%d\n",
+		       smp_num_cpucores);
+	if (smp_num_siblings > 1)
+		printk(KERN_INFO
+		       "cpu package is Multi-Threading capable: number of siblings=%d\n",
+		       smp_num_siblings);
 #endif
 
 	cpu_init();	/* initialize the bootstrap CPU */
@@ -459,12 +505,23 @@
 		   "cpu regs   : %u\n"
 		   "cpu MHz    : %lu.%06lu\n"
 		   "itc MHz    : %lu.%06lu\n"
-		   "BogoMIPS   : %lu.%02lu\n\n",
+		   "BogoMIPS   : %lu.%02lu\n",
 		   cpunum, c->vendor, family, c->model, c->revision, c->archrev,
 		   features, c->ppn, c->number,
 		   c->proc_freq / 1000000, c->proc_freq % 1000000,
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
 		   lpj*HZ/500000, (lpj*HZ/5000) % 100);
+#ifdef CONFIG_SMP
+	seq_printf(m, "siblings   : %u\n", c->num_log);
+	if (c->threads_per_core > 1 || c->cores_per_socket > 1)
+		seq_printf(m,
+		   	   "physical id: %u\n"
+		   	   "core id    : %u\n"
+		   	   "thread id  : %u\n",
+		   	   c->socket_id, c->core_id, c->thread_id);
+#endif
+	seq_printf(m,"\n");
+
 	return 0;
 }
 
@@ -533,6 +590,14 @@
 	memcpy(c->vendor, cpuid.field.vendor, 16);
 #ifdef CONFIG_SMP
 	c->cpu = smp_processor_id();
+
+	/* below default values will be overwritten  by identify_siblings() 
+	 * for Multi-Threading/Multi-Core capable cpu's
+	 */
+	c->threads_per_core = c->cores_per_socket = c->num_log = 1;
+	c->socket_id = -1;
+
+	identify_siblings(c);
 #endif
 	c->ppn = cpuid.field.ppn;
 	c->number = cpuid.field.number;
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 6891d86..499b7e5 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -224,7 +224,8 @@
 	 * could be corrupted.
 	 */
 	retval = (long) &ia64_leave_kernel;
-	if (test_thread_flag(TIF_SYSCALL_TRACE))
+	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	    || test_thread_flag(TIF_SYSCALL_AUDIT))
 		/*
 		 * strace expects to be notified after sigreturn returns even though the
 		 * context to which we return may not be in the middle of a syscall.
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 5318f0c..0d5ee57 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -1,14 +1,25 @@
 /*
  * SMP boot-related support
  *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
+ * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2001, 2004-2005 Intel Corp
+ * 	Rohit Seth <rohit.seth@intel.com>
+ * 	Suresh Siddha <suresh.b.siddha@intel.com>
+ * 	Gordon Jin <gordon.jin@intel.com>
+ *	Ashok Raj  <ashok.raj@intel.com>
  *
  * 01/05/16 Rohit Seth <rohit.seth@intel.com>	Moved SMP booting functions from smp.c to here.
  * 01/04/27 David Mosberger <davidm@hpl.hp.com>	Added ITC synching code.
  * 02/07/31 David Mosberger <davidm@hpl.hp.com>	Switch over to hotplug-CPU boot-sequence.
  *						smp_boot_cpus()/smp_commence() is replaced by
  *						smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
+ * 04/06/21 Ashok Raj		<ashok.raj@intel.com> Added CPU Hotplug Support
+ * 04/12/26 Jin Gordon <gordon.jin@intel.com>
+ * 04/12/26 Rohit Seth <rohit.seth@intel.com>
+ *						Add multi-threading and multi-core detection
+ * 05/01/30 Suresh Siddha <suresh.b.siddha@intel.com>
+ *						Setup cpu_sibling_map and cpu_core_map
  */
 #include <linux/config.h>
 
@@ -58,6 +69,37 @@
 #define Dprintk(x...)
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * Store all idle threads, this can be reused instead of creating
+ * a new thread. Also avoids complicated thread destroy functionality
+ * for idle threads.
+ */
+struct task_struct *idle_thread_array[NR_CPUS];
+
+/*
+ * Global array allocated for NR_CPUS at boot time
+ */
+struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
+
+/*
+ * start_ap in head.S uses this to store current booting cpu
+ * info.
+ */
+struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
+
+#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
+
+#define get_idle_for_cpu(x)		(idle_thread_array[(x)])
+#define set_idle_for_cpu(x,p)	(idle_thread_array[(x)] = (p))
+
+#else
+
+#define get_idle_for_cpu(x)		(NULL)
+#define set_idle_for_cpu(x,p)
+#define set_brendez_area(x)
+#endif
+
 
 /*
  * ITC synchronization related stuff:
@@ -90,6 +132,11 @@
 cpumask_t cpu_possible_map;
 EXPORT_SYMBOL(cpu_possible_map);
 
+cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+int smp_num_siblings = 1;
+int smp_num_cpucores = 1;
+
 /* which logical CPU number maps to which CPU (physical APIC ID) */
 volatile int ia64_cpu_to_sapicid[NR_CPUS];
 EXPORT_SYMBOL(ia64_cpu_to_sapicid);
@@ -124,7 +171,8 @@
 	local_irq_save(flags);
 	{
 		for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
-			while (!go[MASTER]);
+			while (!go[MASTER])
+				cpu_relax();
 			go[MASTER] = 0;
 			go[SLAVE] = ia64_get_itc();
 		}
@@ -147,7 +195,8 @@
 	for (i = 0; i < NUM_ITERS; ++i) {
 		t0 = ia64_get_itc();
 		go[MASTER] = 1;
-		while (!(tm = go[SLAVE]));
+		while (!(tm = go[SLAVE]))
+			cpu_relax();
 		go[SLAVE] = 0;
 		t1 = ia64_get_itc();
 
@@ -226,7 +275,8 @@
 		return;
 	}
 
-	while (go[MASTER]);	/* wait for master to be ready */
+	while (go[MASTER])
+		cpu_relax();	/* wait for master to be ready */
 
 	spin_lock_irqsave(&itc_sync_lock, flags);
 	{
@@ -345,7 +395,6 @@
 {
 	/* Early console may use I/O ports */
 	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
-
 	Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
 	efi_map_pal_code();
 	cpu_init();
@@ -384,6 +433,13 @@
 		.done	= COMPLETION_INITIALIZER(c_idle.done),
 	};
 	DECLARE_WORK(work, do_fork_idle, &c_idle);
+
+ 	c_idle.idle = get_idle_for_cpu(cpu);
+ 	if (c_idle.idle) {
+		init_idle(c_idle.idle, cpu);
+ 		goto do_rest;
+	}
+
 	/*
 	 * We can't use kernel_thread since we must avoid to reschedule the child.
 	 */
@@ -396,10 +452,15 @@
 
 	if (IS_ERR(c_idle.idle))
 		panic("failed fork for CPU %d", cpu);
+
+	set_idle_for_cpu(cpu, c_idle.idle);
+
+do_rest:
 	task_for_booting_cpu = c_idle.idle;
 
 	Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
 
+	set_brendez_area(cpu);
 	platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
 
 	/*
@@ -552,19 +613,70 @@
 	cpu_set(smp_processor_id(), cpu_callin_map);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-extern void fixup_irqs(void);
-/* must be called with cpucontrol mutex held */
-static int __devinit cpu_enable(unsigned int cpu)
-{
-	per_cpu(cpu_state,cpu) = CPU_UP_PREPARE;
-	wmb();
+/*
+ * mt_info[] is a temporary store for all info returned by
+ * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
+ * specific cpu comes.
+ */
+static struct {
+	__u32   socket_id;
+	__u16   core_id;
+	__u16   thread_id;
+	__u16   proc_fixed_addr;
+	__u8    valid;
+}mt_info[NR_CPUS] __devinit;
 
-	while (!cpu_online(cpu))
-		cpu_relax();
-	return 0;
+#ifdef CONFIG_HOTPLUG_CPU
+static inline void
+remove_from_mtinfo(int cpu)
+{
+	int i;
+
+	for_each_cpu(i)
+		if (mt_info[i].valid &&  mt_info[i].socket_id ==
+		    				cpu_data(cpu)->socket_id)
+			mt_info[i].valid = 0;
 }
 
+static inline void
+clear_cpu_sibling_map(int cpu)
+{
+	int i;
+
+	for_each_cpu_mask(i, cpu_sibling_map[cpu])
+		cpu_clear(cpu, cpu_sibling_map[i]);
+	for_each_cpu_mask(i, cpu_core_map[cpu])
+		cpu_clear(cpu, cpu_core_map[i]);
+
+	cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
+}
+
+static void
+remove_siblinginfo(int cpu)
+{
+	int last = 0;
+
+	if (cpu_data(cpu)->threads_per_core == 1 &&
+	    cpu_data(cpu)->cores_per_socket == 1) {
+		cpu_clear(cpu, cpu_core_map[cpu]);
+		cpu_clear(cpu, cpu_sibling_map[cpu]);
+		return;
+	}
+
+	last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0);
+
+	/* remove it from all sibling map's */
+	clear_cpu_sibling_map(cpu);
+
+	/* if this cpu is the last in the core group, remove all its info 
+	 * from mt_info structure
+	 */
+	if (last)
+		remove_from_mtinfo(cpu);
+}
+
+extern void fixup_irqs(void);
+/* must be called with cpucontrol mutex held */
 int __cpu_disable(void)
 {
 	int cpu = smp_processor_id();
@@ -575,9 +687,10 @@
 	if (cpu == 0)
 		return -EBUSY;
 
+	remove_siblinginfo(cpu);
 	fixup_irqs();
 	local_flush_tlb_all();
-	printk ("Disabled cpu %u\n", smp_processor_id());
+	cpu_clear(cpu, cpu_callin_map);
 	return 0;
 }
 
@@ -589,12 +702,7 @@
 		/* They ack this in play_dead by setting CPU_DEAD */
 		if (per_cpu(cpu_state, cpu) == CPU_DEAD)
 		{
-			/*
-			 * TBD: Enable this when physical removal
-			 * or when we put the processor is put in
-			 * SAL_BOOT_RENDEZ mode
-			 * cpu_clear(cpu, cpu_callin_map);
-			 */
+			printk ("CPU %d is now offline\n", cpu);
 			return;
 		}
 		msleep(100);
@@ -602,11 +710,6 @@
  	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
 }
 #else /* !CONFIG_HOTPLUG_CPU */
-static int __devinit cpu_enable(unsigned int cpu)
-{
-	return 0;
-}
-
 int __cpu_disable(void)
 {
 	return -ENOSYS;
@@ -637,6 +740,23 @@
 	       (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
 }
 
+static inline void __devinit
+set_cpu_sibling_map(int cpu)
+{
+	int i;
+
+	for_each_online_cpu(i) {
+		if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
+			cpu_set(i, cpu_core_map[cpu]);
+			cpu_set(cpu, cpu_core_map[i]);
+			if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
+				cpu_set(i, cpu_sibling_map[cpu]);
+				cpu_set(cpu, cpu_sibling_map[i]);
+			}
+		}
+	}
+}
+
 int __devinit
 __cpu_up (unsigned int cpu)
 {
@@ -648,21 +768,26 @@
 		return -EINVAL;
 
 	/*
-	 * Already booted.. just enable and get outa idle lool
+	 * Already booted cpu? not valid anymore since we dont
+	 * do idle loop tightspin anymore.
 	 */
 	if (cpu_isset(cpu, cpu_callin_map))
-	{
-		cpu_enable(cpu);
-		local_irq_enable();
-		while (!cpu_isset(cpu, cpu_online_map))
-			mb();
-		return 0;
-	}
+		return -EINVAL;
+
 	/* Processor goes to start_secondary(), sets online flag */
 	ret = do_boot_cpu(sapicid, cpu);
 	if (ret < 0)
 		return ret;
 
+	if (cpu_data(cpu)->threads_per_core == 1 &&
+	    cpu_data(cpu)->cores_per_socket == 1) {
+		cpu_set(cpu, cpu_sibling_map[cpu]);
+		cpu_set(cpu, cpu_core_map[cpu]);
+		return 0;
+	}
+
+	set_cpu_sibling_map(cpu);
+
 	return 0;
 }
 
@@ -690,3 +815,106 @@
 		       ia64_sal_strerror(sal_ret));
 }
 
+static inline int __devinit
+check_for_mtinfo_index(void)
+{
+	int i;
+	
+	for_each_cpu(i)
+		if (!mt_info[i].valid)
+			return i;
+
+	return -1;
+}
+
+/*
+ * Search the mt_info to find out if this socket's cid/tid information is
+ * cached or not. If the socket exists, fill in the core_id and thread_id 
+ * in cpuinfo
+ */
+static int __devinit
+check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
+{
+	int i;
+	__u32 sid = c->socket_id;
+
+	for_each_cpu(i) {
+		if (mt_info[i].valid && mt_info[i].proc_fixed_addr == logical_address
+		    && mt_info[i].socket_id == sid) {
+			c->core_id = mt_info[i].core_id;
+			c->thread_id = mt_info[i].thread_id;
+			return 1; /* not a new socket */
+		}
+	}
+	return 0;
+}
+
+/*
+ * identify_siblings(cpu) gets called from identify_cpu. This populates the 
+ * information related to logical execution units in per_cpu_data structure.
+ */
+void __devinit
+identify_siblings(struct cpuinfo_ia64 *c)
+{
+	s64 status;
+	u16 pltid;
+	u64 proc_fixed_addr;
+	int count, i;
+	pal_logical_to_physical_t info;
+
+	if (smp_num_cpucores == 1 && smp_num_siblings == 1)
+		return;
+
+	if ((status = ia64_pal_logical_to_phys(0, &info)) != PAL_STATUS_SUCCESS) {
+		printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
+		       status);
+		return;
+	}
+	if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
+		printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
+		return;
+	}
+	if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != PAL_STATUS_SUCCESS) {
+		printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", status);
+		return;
+	}
+
+	c->socket_id =  (pltid << 8) | info.overview_ppid;
+	c->cores_per_socket = info.overview_cpp;
+	c->threads_per_core = info.overview_tpc;
+	count = c->num_log = info.overview_num_log;
+
+	/* If the thread and core id information is already cached, then
+	 * we will simply update cpu_info and return. Otherwise, we will
+	 * do the PAL calls and cache core and thread id's of all the siblings.
+	 */
+	if (check_for_new_socket(proc_fixed_addr, c))
+		return;
+
+	for (i = 0; i < count; i++) {
+		int index;
+
+		if (i && (status = ia64_pal_logical_to_phys(i, &info))
+			  != PAL_STATUS_SUCCESS) {
+                	printk(KERN_ERR "ia64_pal_logical_to_phys failed"
+					" with %ld\n", status);
+                	return;
+		}
+		if (info.log2_la == proc_fixed_addr) {
+			c->core_id = info.log1_cid;
+			c->thread_id = info.log1_tid;
+		}
+
+		index = check_for_mtinfo_index();
+		/* We will not do the mt_info caching optimization in this case.
+		 */
+		if (index < 0)
+			continue;
+
+		mt_info[index].valid = 1;
+		mt_info[index].socket_id = c->socket_id;
+		mt_info[index].core_id = info.log1_cid;
+		mt_info[index].thread_id = info.log1_tid;
+		mt_info[index].proc_fixed_addr = info.log2_la;
+	}
+}
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 3ac216e..a8cf6d8 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -93,20 +93,6 @@
 }
 
 asmlinkage unsigned long
-ia64_shmat (int shmid, void __user *shmaddr, int shmflg)
-{
-	unsigned long raddr;
-	int retval;
-
-	retval = do_shmat(shmid, shmaddr, shmflg, &raddr);
-	if (retval < 0)
-		return retval;
-
-	force_successful_syscall_return();
-	return raddr;
-}
-
-asmlinkage unsigned long
 ia64_brk (unsigned long brk)
 {
 	unsigned long rlim, retval, newbrk, oldbrk;
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index d494ff6..2776a07 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1943,23 +1943,30 @@
 int
 unw_unwind_to_user (struct unw_frame_info *info)
 {
-	unsigned long ip, sp;
+	unsigned long ip, sp, pr = 0;
 
 	while (unw_unwind(info) >= 0) {
-		if (unw_get_rp(info, &ip) < 0) {
-			unw_get_ip(info, &ip);
-			UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
-				   __FUNCTION__, ip);
+		unw_get_sp(info, &sp);
+		if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
+		    < IA64_PT_REGS_SIZE) {
+			UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
+				   __FUNCTION__);
+			break;
+		}
+		if (unw_is_intr_frame(info) &&
+		    (pr & (1UL << PRED_USER_STACK)))
+			return 0;
+		if (unw_get_pr (info, &pr) < 0) {
+			unw_get_rp(info, &ip);
+			UNW_DPRINT(0, "unwind.%s: failed to read "
+				   "predicate register (ip=0x%lx)\n",
+				__FUNCTION__, ip);
 			return -1;
 		}
-		unw_get_sp(info, &sp);
-		if (sp >= (unsigned long)info->task + IA64_STK_OFFSET)
-			break;
-		if (ip < FIXADDR_USER_END)
-			return 0;
 	}
 	unw_get_ip(info, &ip);
-	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
+	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
+		   __FUNCTION__, ip);
 	return -1;
 }
 EXPORT_SYMBOL(unw_unwind_to_user);
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 29c802b..a1af914 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -1,8 +1,8 @@
 /*
  * Cache flushing routines.
  *
- * Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <asm/asmmacro.h>
 #include <asm/page.h>
@@ -26,7 +26,7 @@
 
 	mov ar.lc=r8
 	;;
-.Loop:	fc in0				// issuable on M0 only
+.Loop:	fc.i in0			// issuable on M2 only
 	add in0=32,in0
 	br.cloop.sptk.few .Loop
 	;;
diff --git a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S
index 6f26ef7..6f308e6 100644
--- a/arch/ia64/lib/memcpy_mck.S
+++ b/arch/ia64/lib/memcpy_mck.S
@@ -75,6 +75,7 @@
 	mov	f6=f0
 	br.cond.sptk .common_code
 	;;
+END(memcpy)
 GLOBAL_ENTRY(__copy_user)
 	.prologue
 // check dest alignment
@@ -300,7 +301,7 @@
 	add	src_pre_mem=0,src0	// prefetch src pointer
 	add	dst_pre_mem=0,dst0	// prefetch dest pointer
 	and	src0=-8,src0		// 1st src pointer
-(p7)	mov	ar.lc = r21
+(p7)	mov	ar.lc = cnt
 (p8)	mov	ar.lc = r0
 	;;
 	TEXT_ALIGN(32)
@@ -524,7 +525,6 @@
 #undef B
 #undef C
 #undef D
-END(memcpy)
 
 /*
  * Due to lack of local tag support in gcc 2.x assembler, it is not clear which
diff --git a/arch/ia64/lib/memset.S b/arch/ia64/lib/memset.S
index bd8cf90..f26c16a 100644
--- a/arch/ia64/lib/memset.S
+++ b/arch/ia64/lib/memset.S
@@ -57,10 +57,10 @@
 { .mmi
 	.prologue
 	alloc	tmp = ar.pfs, 3, 0, 0, 0
-	.body
 	lfetch.nt1 [dest]			//
 	.save   ar.lc, save_lc
 	mov.i	save_lc = ar.lc
+	.body
 } { .mmi
 	mov	ret0 = dest			// return value
 	cmp.ne	p_nz, p_zr = value, r0		// use stf.spill if value is zero
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 6daf15a..91a055f 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -61,7 +61,8 @@
 	printk("%d reserved pages\n", reserved);
 	printk("%d pages shared\n", shared);
 	printk("%d pages swap cached\n", cached);
-	printk("%ld pages in page table cache\n", pgtable_cache_size);
+	printk("%ld pages in page table cache\n",
+		pgtable_quicklist_total_size());
 }
 
 /* physical address where the bootmem map is located */
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 3456a9b..c007109 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -582,7 +582,8 @@
 	printk("%d reserved pages\n", total_reserved);
 	printk("%d pages shared\n", total_shared);
 	printk("%d pages swap cached\n", total_cached);
-	printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
+	printk("Total of %ld pages in page table cache\n",
+		pgtable_quicklist_total_size());
 	printk("%d free buffer pages\n", nr_free_buffer_pages());
 }
 
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index da85912..4174ec9 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -209,10 +209,13 @@
 	}
 
   no_context:
-	if (isr & IA64_ISR_SP) {
+	if ((isr & IA64_ISR_SP)
+	    || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
+	{
 		/*
-		 * This fault was due to a speculative load set the "ed" bit in the psr to
-		 * ensure forward progress (target register will get a NaT).
+		 * This fault was due to a speculative load or lfetch.fault, set the "ed"
+		 * bit in the psr to ensure forward progress.  (Target register will get a
+		 * NaT for ld.s, lfetch will be canceled.)
 		 */
 		ia64_psr(regs)->ed = 1;
 		return;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 65cf839..547785e 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -39,6 +39,9 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
+DEFINE_PER_CPU(unsigned long *, __pgtable_quicklist);
+DEFINE_PER_CPU(long, __pgtable_quicklist_size);
+
 extern void ia64_tlb_init (void);
 
 unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
@@ -50,27 +53,53 @@
 EXPORT_SYMBOL(vmem_map);
 #endif
 
-static int pgt_cache_water[2] = { 25, 50 };
-
-struct page *zero_page_memmap_ptr;		/* map entry for zero page */
+struct page *zero_page_memmap_ptr;	/* map entry for zero page */
 EXPORT_SYMBOL(zero_page_memmap_ptr);
 
-void
-check_pgt_cache (void)
-{
-	int low, high;
+#define MIN_PGT_PAGES			25UL
+#define MAX_PGT_FREES_PER_PASS		16L
+#define PGT_FRACTION_OF_NODE_MEM	16
 
-	low = pgt_cache_water[0];
-	high = pgt_cache_water[1];
+static inline long
+max_pgt_pages(void)
+{
+	u64 node_free_pages, max_pgt_pages;
+
+#ifndef	CONFIG_NUMA
+	node_free_pages = nr_free_pages();
+#else
+	node_free_pages = nr_free_pages_pgdat(NODE_DATA(numa_node_id()));
+#endif
+	max_pgt_pages = node_free_pages / PGT_FRACTION_OF_NODE_MEM;
+	max_pgt_pages = max(max_pgt_pages, MIN_PGT_PAGES);
+	return max_pgt_pages;
+}
+
+static inline long
+min_pages_to_free(void)
+{
+	long pages_to_free;
+
+	pages_to_free = pgtable_quicklist_size - max_pgt_pages();
+	pages_to_free = min(pages_to_free, MAX_PGT_FREES_PER_PASS);
+	return pages_to_free;
+}
+
+void
+check_pgt_cache(void)
+{
+	long pages_to_free;
+
+	if (unlikely(pgtable_quicklist_size <= MIN_PGT_PAGES))
+		return;
 
 	preempt_disable();
-	if (pgtable_cache_size > (u64) high) {
-		do {
-			if (pgd_quicklist)
-				free_page((unsigned long)pgd_alloc_one_fast(NULL));
-			if (pmd_quicklist)
-				free_page((unsigned long)pmd_alloc_one_fast(NULL, 0));
-		} while (pgtable_cache_size > (u64) low);
+	while (unlikely((pages_to_free = min_pages_to_free()) > 0)) {
+		while (pages_to_free--) {
+			free_page((unsigned long)pgtable_quicklist_alloc());
+		}
+		preempt_enable();
+		preempt_disable();
 	}
 	preempt_enable();
 }
@@ -523,11 +552,14 @@
 mem_init (void)
 {
 	long reserved_pages, codesize, datasize, initsize;
-	unsigned long num_pgt_pages;
 	pg_data_t *pgdat;
 	int i;
 	static struct kcore_list kcore_mem, kcore_vmem, kcore_kernel;
 
+	BUG_ON(PTRS_PER_PGD * sizeof(pgd_t) != PAGE_SIZE);
+	BUG_ON(PTRS_PER_PMD * sizeof(pmd_t) != PAGE_SIZE);
+	BUG_ON(PTRS_PER_PTE * sizeof(pte_t) != PAGE_SIZE);
+
 #ifdef CONFIG_PCI
 	/*
 	 * This needs to be called _after_ the command line has been parsed but _before_
@@ -564,18 +596,6 @@
 	       num_physpages << (PAGE_SHIFT - 10), codesize >> 10,
 	       reserved_pages << (PAGE_SHIFT - 10), datasize >> 10, initsize >> 10);
 
-	/*
-	 * Allow for enough (cached) page table pages so that we can map the entire memory
-	 * at least once.  Each task also needs a couple of page tables pages, so add in a
-	 * fudge factor for that (don't use "threads-max" here; that would be wrong!).
-	 * Don't allow the cache to be more than 10% of total memory, though.
-	 */
-#	define NUM_TASKS	500	/* typical number of tasks */
-	num_pgt_pages = nr_free_pages() / PTRS_PER_PGD + NUM_TASKS;
-	if (num_pgt_pages > nr_free_pages() / 10)
-		num_pgt_pages = nr_free_pages() / 10;
-	if (num_pgt_pages > (u64) pgt_cache_water[1])
-		pgt_cache_water[1] = num_pgt_pages;
 
 	/*
 	 * For fsyscall entrpoints with no light-weight handler, use the ordinary
diff --git a/arch/ia64/sn/include/pci/pcibr_provider.h b/arch/ia64/sn/include/pci/pcibr_provider.h
index b1f05ff..1cd291d 100644
--- a/arch/ia64/sn/include/pci/pcibr_provider.h
+++ b/arch/ia64/sn/include/pci/pcibr_provider.h
@@ -123,9 +123,11 @@
 }
 #define pcibr_unlock(pcibus_info, flag)  spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag)
 
+extern int  pcibr_init_provider(void);
 extern void *pcibr_bus_fixup(struct pcibus_bussoft *);
-extern uint64_t pcibr_dma_map(struct pcidev_info *, unsigned long, size_t, unsigned int);
-extern void pcibr_dma_unmap(struct pcidev_info *, dma_addr_t, int);
+extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
+extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t);
+extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
 
 /*
  * prototypes for the bridge asic register access routines in pcibr_reg.c
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 6c7f4d9..4351c4f 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -4,9 +4,15 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1999,2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
+# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
 obj-y				+= setup.o bte.o bte_error.o irq.o mca.o idle.o \
 				   huberror.o io_init.o iomv.o klconflib.o sn2/
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
+obj-$(CONFIG_SGI_TIOCX)		+= tiocx.o
+obj-$(CONFIG_IA64_SGI_SN_XP)	+= xp.o
+xp-y				:= xp_main.o xp_nofault.o
+obj-$(CONFIG_IA64_SGI_SN_XP)	+= xpc.o
+xpc-y				:= xpc_main.o xpc_channel.o xpc_partition.o
+obj-$(CONFIG_IA64_SGI_SN_XP)	+= xpnet.o
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index ce0bc40..647deae 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/config.h>
@@ -170,10 +170,6 @@
 	/* Initialize the notification to a known value. */
 	*bte->most_rcnt_na = BTE_WORD_BUSY;
 
-	/* Set the status reg busy bit and transfer length */
-	BTE_PRINTKV(("IBLS = 0x%lx\n", IBLS_BUSY | transfer_size));
-	BTE_LNSTAT_STORE(bte, IBLS_BUSY | transfer_size);
-
 	/* Set the source and destination registers */
 	BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src))));
 	BTE_SRC_STORE(bte, TO_PHYS(src));
@@ -188,7 +184,7 @@
 
 	/* Initiate the transfer */
 	BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode)));
-	BTE_CTRL_STORE(bte, BTE_VALID_MODE(mode));
+	BTE_START_TRANSFER(bte, transfer_size, BTE_VALID_MODE(mode));
 
 	itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec);
 
@@ -429,10 +425,16 @@
 	mynodepda->bte_recovery_timer.data = (unsigned long)mynodepda;
 
 	for (i = 0; i < BTES_PER_NODE; i++) {
+		u64 *base_addr;
+
 		/* Which link status register should we use? */
-		unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1);
-		mynodepda->bte_if[i].bte_base_addr = (u64 *)
-		    REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status);
+		base_addr = (u64 *)
+		    REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), BTE_BASE_ADDR(i));
+		mynodepda->bte_if[i].bte_base_addr = base_addr;
+		mynodepda->bte_if[i].bte_source_addr = BTE_SOURCE_ADDR(base_addr);
+		mynodepda->bte_if[i].bte_destination_addr = BTE_DEST_ADDR(base_addr);
+		mynodepda->bte_if[i].bte_control_addr = BTE_CTRL_ADDR(base_addr);
+		mynodepda->bte_if[i].bte_notify_addr = BTE_NOTIF_ADDR(base_addr);
 
 		/*
 		 * Initialize the notification and spinlock
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c
index fd10431..fcbc748 100644
--- a/arch/ia64/sn/kernel/bte_error.c
+++ b/arch/ia64/sn/kernel/bte_error.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/types.h>
@@ -33,48 +33,28 @@
  * Wait until all BTE related CRBs are completed
  * and then reset the interfaces.
  */
-void bte_error_handler(unsigned long _nodepda)
+void shub1_bte_error_handler(unsigned long _nodepda)
 {
 	struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
-	spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
 	struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
 	nasid_t nasid;
 	int i;
 	int valid_crbs;
-	unsigned long irq_flags;
-	volatile u64 *notify;
-	bte_result_t bh_error;
 	ii_imem_u_t imem;	/* II IMEM Register */
 	ii_icrb0_d_u_t icrbd;	/* II CRB Register D */
 	ii_ibcr_u_t ibcr;
 	ii_icmr_u_t icmr;
 	ii_ieclr_u_t ieclr;
 
-	BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
+	BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
 		    smp_processor_id()));
 
-	spin_lock_irqsave(recovery_lock, irq_flags);
-
 	if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
 	    (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
 		BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
 			    smp_processor_id()));
-		spin_unlock_irqrestore(recovery_lock, irq_flags);
 		return;
 	}
-	/*
-	 * Lock all interfaces on this node to prevent new transfers
-	 * from being queued.
-	 */
-	for (i = 0; i < BTES_PER_NODE; i++) {
-		if (err_nodepda->bte_if[i].cleanup_active) {
-			continue;
-		}
-		spin_lock(&err_nodepda->bte_if[i].spinlock);
-		BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
-			    smp_processor_id(), i));
-		err_nodepda->bte_if[i].cleanup_active = 1;
-	}
 
 	/* Determine information about our hub */
 	nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
@@ -101,7 +81,6 @@
 		mod_timer(recovery_timer, HZ * 5);
 		BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
 			    smp_processor_id()));
-		spin_unlock_irqrestore(recovery_lock, irq_flags);
 		return;
 	}
 	if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
@@ -120,8 +99,6 @@
 				BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
 					    err_nodepda, smp_processor_id(),
 					    i));
-				spin_unlock_irqrestore(recovery_lock,
-						       irq_flags);
 				return;
 			}
 		}
@@ -146,6 +123,51 @@
 	ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
 	REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
 
+	del_timer(recovery_timer);
+}
+
+/*
+ * Wait until all BTE related CRBs are completed
+ * and then reset the interfaces.
+ */
+void bte_error_handler(unsigned long _nodepda)
+{
+	struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
+	spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
+	int i;
+	nasid_t nasid;
+	unsigned long irq_flags;
+	volatile u64 *notify;
+	bte_result_t bh_error;
+
+	BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
+		    smp_processor_id()));
+
+	spin_lock_irqsave(recovery_lock, irq_flags);
+
+	/*
+	 * Lock all interfaces on this node to prevent new transfers
+	 * from being queued.
+	 */
+	for (i = 0; i < BTES_PER_NODE; i++) {
+		if (err_nodepda->bte_if[i].cleanup_active) {
+			continue;
+		}
+		spin_lock(&err_nodepda->bte_if[i].spinlock);
+		BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
+			    smp_processor_id(), i));
+		err_nodepda->bte_if[i].cleanup_active = 1;
+	}
+
+	if (is_shub1()) {
+		shub1_bte_error_handler(_nodepda);
+	} else {
+		nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
+
+		if (ia64_sn_bte_recovery(nasid))
+			panic("bte_error_handler(): Fatal BTE Error");
+	}
+
 	for (i = 0; i < BTES_PER_NODE; i++) {
 		bh_error = err_nodepda->bte_if[i].bh_error;
 		if (bh_error != BTE_SUCCESS) {
@@ -165,8 +187,6 @@
 		spin_unlock(&err_nodepda->bte_if[i].spinlock);
 	}
 
-	del_timer(recovery_timer);
-
 	spin_unlock_irqrestore(recovery_lock, irq_flags);
 }
 
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 2bdf684..5c39b43 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000,2002-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/types.h>
@@ -38,8 +38,11 @@
 	if ((int)ret_stuff.v0)
 		panic("hubii_eint_handler(): Fatal TIO Error");
 
-	if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
-		(void)hubiio_crb_error_handler(hubdev_info);
+	if (is_shub1()) {
+		if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
+			(void)hubiio_crb_error_handler(hubdev_info);
+	} else 
+		bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 0018808..9e07f54 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -11,14 +11,15 @@
 #include <asm/sn/types.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 #include "xtalk/xwidgetdev.h"
 #include <asm/sn/geo.h>
 #include "xtalk/hubdev.h"
 #include <asm/sn/io.h>
 #include <asm/sn/simulator.h>
+#include <asm/sn/tioca_provider.h>
 
 char master_baseio_wid;
 nasid_t master_nasid = INVALID_NASID;	/* Partition Master */
@@ -34,6 +35,37 @@
 
 int sn_ioif_inited = 0;		/* SN I/O infrastructure initialized? */
 
+struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES];	/* indexed by asic type */
+
+/*
+ * Hooks and struct for unsupported pci providers
+ */
+
+static dma_addr_t
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size)
+{
+	return 0;
+}
+
+static void
+sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
+{
+	return;
+}
+
+static void *
+sn_default_pci_bus_fixup(struct pcibus_bussoft *soft)
+{
+	return NULL;
+}
+
+static struct sn_pcibus_provider sn_pci_default_provider = {
+	.dma_map = sn_default_pci_map,
+	.dma_map_consistent = sn_default_pci_map,
+	.dma_unmap = sn_default_pci_unmap,
+	.bus_fixup = sn_default_pci_bus_fixup,
+};
+
 /*
  * Retrieve the DMA Flush List given nasid.  This list is needed 
  * to implement the WAR - Flush DMA data on PIO Reads.
@@ -142,6 +174,12 @@
 		if (status)
 			continue;
 
+		/* Attach the error interrupt handlers */
+		if (nasid & 1)
+			ice_error_init(hubdev);
+		else
+			hub_error_init(hubdev);
+
 		for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
 			hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
 
@@ -179,10 +217,6 @@
 			    sn_flush_device_list;
 		}
 
-		if (!(i & 1))
-			hub_error_init(hubdev);
-		else
-			ice_error_init(hubdev);
 	}
 
 }
@@ -201,6 +235,7 @@
 	struct sn_irq_info *sn_irq_info;
 	struct pci_dev *host_pci_dev;
 	int status = 0;
+	struct pcibus_bussoft *bs;
 
 	dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
 	if (SN_PCIDEV_INFO(dev) <= 0)
@@ -241,6 +276,7 @@
 	}
 
 	/* set up host bus linkages */
+	bs = SN_PCIBUS_BUSSOFT(dev->bus);
 	host_pci_dev =
 	    pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32,
 			  SN_PCIDEV_INFO(dev)->
@@ -248,10 +284,16 @@
 	SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info =
 	    SN_PCIDEV_INFO(host_pci_dev);
 	SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev;
-	SN_PCIDEV_INFO(dev)->pdi_pcibus_info = SN_PCIBUS_BUSSOFT(dev->bus);
+	SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs;
+
+	if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
+		SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
+	} else {
+		SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
+	}
 
 	/* Only set up IRQ stuff if this device has a host bus context */
-	if (SN_PCIDEV_BUSSOFT(dev) && sn_irq_info->irq_irq) {
+	if (bs && sn_irq_info->irq_irq) {
 		SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info;
 		dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq;
 		sn_irq_fixup(dev, sn_irq_info);
@@ -271,6 +313,7 @@
 	struct pcibus_bussoft *prom_bussoft_ptr;
 	struct hubdev_info *hubdev_info;
 	void *provider_soft;
+	struct sn_pcibus_provider *provider;
 
 	status =
 	    sal_get_pcibus_info((u64) segment, (u64) busnum,
@@ -291,16 +334,22 @@
 	/*
 	 * Per-provider fixup.  Copies the contents from prom to local
 	 * area and links SN_PCIBUS_BUSSOFT().
-	 *
-	 * Note:  Provider is responsible for ensuring that prom_bussoft_ptr
-	 * represents an asic-type that it can handle.
 	 */
 
-	if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) {
-		return;		/* no further fixup necessary */
+	if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
+		return;		/* unsupported asic type */
 	}
 
-	provider_soft = pcibr_bus_fixup(prom_bussoft_ptr);
+	provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
+	if (provider == NULL) {
+		return;		/* no provider registerd for this asic */
+	}
+
+	provider_soft = NULL;
+	if (provider->bus_fixup) {
+		provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr);
+	}
+
 	if (provider_soft == NULL) {
 		return;		/* fixup failed or not applicable */
 	}
@@ -339,6 +388,17 @@
 		return 0;
 
 	/*
+	 * prime sn_pci_provider[].  Individial provider init routines will
+	 * override their respective default entries.
+	 */
+
+	for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
+		sn_pci_provider[i] = &sn_pci_default_provider;
+
+	pcibr_init_provider();
+	tioca_init_provider();
+
+	/*
 	 * This is needed to avoid bounce limit checks in the blk layer
 	 */
 	ia64_max_iommu_merge_mask = ~PAGE_MASK;
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 3be4472..0f4e8138 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -13,8 +13,8 @@
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 #include "xtalk/xwidgetdev.h"
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/sn_sal.h>
@@ -82,20 +82,9 @@
 	nasid = get_nasid();
 	event_occurred =
 	    HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED));
-	if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
-		mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
-	}
-	if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) {
-		mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT);
-	}
-	if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) {
-		mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT);
-	}
-	if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
-		mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
-	}
+	mask = event_occurred & SH_ALL_INT_MASK;
 	HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS),
-	      mask);
+		 mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
 	move_irq(irq);
diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
index 857774b..6546db6 100644
--- a/arch/ia64/sn/kernel/mca.c
+++ b/arch/ia64/sn/kernel/mca.c
@@ -37,6 +37,11 @@
  * This function is the callback routine that SAL calls to log error
  * info for platform errors.  buf is appended to sn_oemdata, resizing as
  * required.
+ * Note: this is a SAL to OS callback, running under the same rules as the SAL
+ * code.  SAL calls are run with preempt disabled so this routine must not
+ * sleep.  vmalloc can sleep so print_hook cannot resize the output buffer
+ * itself, instead it must set the required size and return to let the caller
+ * resize the buffer then redrive the SAL call.
  */
 static int print_hook(const char *fmt, ...)
 {
@@ -47,18 +52,8 @@
 	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
 	len = strlen(buf);
-	while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {
-		u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);
-		if (!newbuf) {
-			printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
-			       __FUNCTION__);
-			return 0;
-		}
-		memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);
-		vfree(*sn_oemdata);
-		*sn_oemdata = newbuf;
-	}
-	memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);
+	if (*sn_oemdata_size + len <= sn_oemdata_bufsize)
+		memcpy(*sn_oemdata + *sn_oemdata_size, buf, len);
 	*sn_oemdata_size += len;
 	return 0;
 }
@@ -98,7 +93,20 @@
 	sn_oemdata = oemdata;
 	sn_oemdata_size = oemdata_size;
 	sn_oemdata_bufsize = 0;
-	ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
+	*sn_oemdata_size = PAGE_SIZE;	/* first guess at how much data will be generated */
+	while (*sn_oemdata_size > sn_oemdata_bufsize) {
+		u8 *newbuf = vmalloc(*sn_oemdata_size);
+		if (!newbuf) {
+			printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
+			       __FUNCTION__);
+			return 1;
+		}
+		vfree(*sn_oemdata);
+		*sn_oemdata = newbuf;
+		sn_oemdata_bufsize = *sn_oemdata_size;
+		*sn_oemdata_size = 0;
+		ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
+	}
 	up(&sn_oemdata_mutex);
 	return 0;
 }
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index f0306b5..4fb4498 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/config.h>
@@ -29,6 +29,7 @@
 #include <linux/sched.h>
 #include <linux/root_dev.h>
 #include <linux/nodemask.h>
+#include <linux/pm.h>
 
 #include <asm/io.h>
 #include <asm/sal.h>
@@ -72,6 +73,12 @@
 DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
 EXPORT_PER_CPU_SYMBOL(__sn_hub_info);
 
+DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]);
+EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);
+
+DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);
+EXPORT_PER_CPU_SYMBOL(__sn_nodepda);
+
 partid_t sn_partid = -1;
 EXPORT_SYMBOL(sn_partid);
 char sn_system_serial_number_string[128];
@@ -353,6 +360,14 @@
 	screen_info = sn_screen_info;
 
 	sn_timer_init();
+
+	/*
+	 * set pm_power_off to a SAL call to allow
+	 * sn machines to power off. The SAL call can be replaced
+	 * by an ACPI interface call when ACPI is fully implemented
+	 * for sn.
+	 */
+	pm_power_off = ia64_sn_power_down;
 }
 
 /**
@@ -364,11 +379,11 @@
 {
 	cnodeid_t cnode;
 
-	memset(pda->cnodeid_to_nasid_table, -1,
-	       sizeof(pda->cnodeid_to_nasid_table));
+	memset(sn_cnodeid_to_nasid, -1,
+			sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
 	for_each_online_node(cnode)
-		pda->cnodeid_to_nasid_table[cnode] =
-		    pxm_to_nasid(nid_to_pxm_map[cnode]);
+		sn_cnodeid_to_nasid[cnode] =
+				pxm_to_nasid(nid_to_pxm_map[cnode]);
 
 	numionodes = num_online_nodes();
 	scan_for_ionodes();
@@ -468,7 +483,8 @@
 
 	cnode = nasid_to_cnodeid(nasid);
 
-	pda->p_nodepda = nodepdaindr[cnode];
+	sn_nodepda = nodepdaindr[cnode];
+
 	pda->led_address =
 	    (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
 	pda->led_state = LED_ALWAYS_SET;
@@ -477,15 +493,18 @@
 	pda->idle_flag = 0;
 
 	if (cpuid != 0) {
-		memcpy(pda->cnodeid_to_nasid_table,
-		       pdacpu(0)->cnodeid_to_nasid_table,
-		       sizeof(pda->cnodeid_to_nasid_table));
+		/* copy cpu 0's sn_cnodeid_to_nasid table to this cpu's */
+		memcpy(sn_cnodeid_to_nasid,
+		       (&per_cpu(__sn_cnodeid_to_nasid, 0)),
+		       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
 	}
 
 	/*
 	 * Check for WARs.
 	 * Only needs to be done once, on BSP.
-	 * Has to be done after loop above, because it uses pda.cnodeid_to_nasid_table[i].
+	 * Has to be done after loop above, because it uses this cpu's
+	 * sn_cnodeid_to_nasid table which was just initialized if this
+	 * isn't cpu 0.
 	 * Has to be done before assignment below.
 	 */
 	if (!wars_have_been_checked) {
@@ -571,8 +590,7 @@
 		brd = find_lboard_any(brd, KLTYPE_SNIA);
 
 		while (brd) {
-			pda->cnodeid_to_nasid_table[numionodes] =
-			    brd->brd_nasid;
+			sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
 			physical_node_map[brd->brd_nasid] = numionodes;
 			root_lboard[numionodes] = brd;
 			numionodes++;
@@ -593,8 +611,7 @@
 				      root_lboard[nasid_to_cnodeid(nasid)],
 				      KLTYPE_TIO);
 		while (brd) {
-			pda->cnodeid_to_nasid_table[numionodes] =
-			    brd->brd_nasid;
+			sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
 			physical_node_map[brd->brd_nasid] = numionodes;
 			root_lboard[numionodes] = brd;
 			numionodes++;
@@ -605,7 +622,6 @@
 			brd = find_lboard_any(brd, KLTYPE_TIO);
 		}
 	}
-
 }
 
 int
@@ -614,7 +630,8 @@
 	long cpu;
 	
 	for (cpu=0; cpu < NR_CPUS; cpu++) 
-		if (nodepda->phys_cpuid[cpu].nasid == nasid && nodepda->phys_cpuid[cpu].slice == slice)
+		if (cpuid_to_nasid(cpu) == nasid &&
+					cpuid_to_slice(cpu) == slice)
 			return cpu;
 
 	return -1;
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 1973564..833e700 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -28,6 +28,7 @@
 #include <linux/vmalloc.h>
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
+#include <linux/utsname.h>
 #include <linux/cpumask.h>
 #include <linux/smp_lock.h>
 #include <linux/nodemask.h>
@@ -43,6 +44,7 @@
 #include <asm/sn/module.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/sn2/sn_hwperf.h>
+#include <asm/sn/addrs.h>
 
 static void *sn_hwperf_salheap = NULL;
 static int sn_hwperf_obj_cnt = 0;
@@ -81,26 +83,45 @@
 	return e;
 }
 
+static int sn_hwperf_location_to_bpos(char *location,
+	int *rack, int *bay, int *slot, int *slab)
+{
+	char type;
+
+	/* first scan for an old style geoid string */
+	if (sscanf(location, "%03d%c%02d#%d",
+		rack, &type, bay, slab) == 4)
+		*slot = 0; 
+	else /* scan for a new bladed geoid string */
+	if (sscanf(location, "%03d%c%02d^%02d#%d",
+		rack, &type, bay, slot, slab) != 5)
+		return -1; 
+	/* success */
+	return 0;
+}
+
 static int sn_hwperf_geoid_to_cnode(char *location)
 {
 	int cnode;
 	geoid_t geoid;
 	moduleid_t module_id;
-	char type;
-	int rack, slot, slab;
-	int this_rack, this_slot, this_slab;
+	int rack, bay, slot, slab;
+	int this_rack, this_bay, this_slot, this_slab;
 
-	if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4)
+	if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
 		return -1;
 
 	for (cnode = 0; cnode < numionodes; cnode++) {
 		geoid = cnodeid_get_geoid(cnode);
 		module_id = geo_module(geoid);
 		this_rack = MODULE_GET_RACK(module_id);
-		this_slot = MODULE_GET_BPOS(module_id);
+		this_bay = MODULE_GET_BPOS(module_id);
+		this_slot = geo_slot(geoid);
 		this_slab = geo_slab(geoid);
-		if (rack == this_rack && slot == this_slot && slab == this_slab)
+		if (rack == this_rack && bay == this_bay &&
+			slot == this_slot && slab == this_slab) {
 			break;
+		}
 	}
 
 	return cnode < numionodes ? cnode : -1;
@@ -153,11 +174,36 @@
 	return slabname;
 }
 
+static void print_pci_topology(struct seq_file *s,
+	struct sn_hwperf_object_info *obj, int *ordinal,
+	u64 rack, u64 bay, u64 slot, u64 slab)
+{
+	char *p1;
+	char *p2;
+	char *pg;
+
+	if (!(pg = (char *)get_zeroed_page(GFP_KERNEL)))
+		return; /* ignore */
+	if (ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab,
+		__pa(pg), PAGE_SIZE) == SN_HWPERF_OP_OK) {
+		for (p1=pg; *p1 && p1 < pg + PAGE_SIZE;) {
+			if (!(p2 = strchr(p1, '\n')))
+				break;
+			*p2 = '\0';
+			seq_printf(s, "pcibus %d %s-%s\n",
+				*ordinal, obj->location, p1);
+			(*ordinal)++;
+			p1 = p2 + 1;
+		}
+	}
+	free_page((unsigned long)pg);
+}
+
 static int sn_topology_show(struct seq_file *s, void *d)
 {
 	int sz;
 	int pt;
-	int e;
+	int e = 0;
 	int i;
 	int j;
 	const char *slabname;
@@ -169,11 +215,44 @@
 	struct sn_hwperf_object_info *p;
 	struct sn_hwperf_object_info *obj = d;	/* this object */
 	struct sn_hwperf_object_info *objs = s->private; /* all objects */
+	int rack, bay, slot, slab;
+	u8 shubtype;
+	u8 system_size;
+	u8 sharing_size;
+	u8 partid;
+	u8 coher;
+	u8 nasid_shift;
+	u8 region_size;
+	u16 nasid_mask;
+	int nasid_msb;
+	int pci_bus_ordinal = 0;
 
 	if (obj == objs) {
-		seq_printf(s, "# sn_topology version 1\n");
+		seq_printf(s, "# sn_topology version 2\n");
 		seq_printf(s, "# objtype ordinal location partition"
 			" [attribute value [, ...]]\n");
+
+		if (ia64_sn_get_sn_info(0,
+			&shubtype, &nasid_mask, &nasid_shift, &system_size,
+			&sharing_size, &partid, &coher, &region_size))
+			BUG();
+		for (nasid_msb=63; nasid_msb > 0; nasid_msb--) {
+			if (((u64)nasid_mask << nasid_shift) & (1ULL << nasid_msb))
+				break;
+		}
+		seq_printf(s, "partition %u %s local "
+			"shubtype %s, "
+			"nasid_mask 0x%016lx, "
+			"nasid_bits %d:%d, "
+			"system_size %d, "
+			"sharing_size %d, "
+			"coherency_domain %d, "
+			"region_size %d\n",
+
+			partid, system_utsname.nodename,
+			shubtype ? "shub2" : "shub1", 
+			(u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
+			system_size, sharing_size, coher, region_size);
 	}
 
 	if (SN_HWPERF_FOREIGN(obj)) {
@@ -181,7 +260,7 @@
 		return 0;
 	}
 
-	for (i = 0; obj->name[i]; i++) {
+	for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) {
 		if (obj->name[i] == ' ')
 			obj->name[i] = '_';
 	}
@@ -221,6 +300,17 @@
 				seq_putc(s, '\n');
 			}
 		}
+
+		/*
+		 * PCI busses attached to this node, if any
+		 */
+		if (sn_hwperf_location_to_bpos(obj->location,
+			&rack, &bay, &slot, &slab)) {
+			/* export pci bus info */
+			print_pci_topology(s, obj, &pci_bus_ordinal,
+				rack, bay, slot, slab);
+
+		}
 	}
 
 	if (obj->ports) {
@@ -397,6 +487,9 @@
 		break;
 
 	case SN_HWPERF_OP_BUSY:
+		e = -EBUSY;
+		break;
+
 	case SN_HWPERF_OP_RECONFIGURE:
 		e = -EAGAIN;
 		break;
@@ -549,6 +642,7 @@
 		r = sn_hwperf_op_cpu(&op_info);
 		if (r) {
 			r = sn_hwperf_map_err(r);
+			a.v0 = v0;
 			goto error;
 		}
 		break;
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
new file mode 100644
index 0000000..ab9b5f3
--- /dev/null
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -0,0 +1,552 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
+#include <asm/sn/types.h>
+#include <asm/sn/shubio.h>
+#include <asm/sn/tiocx.h>
+#include <asm/sn/l1.h>
+#include <asm/sn/module.h>
+#include "tio.h"
+#include "xtalk/xwidgetdev.h"
+#include "xtalk/hubdev.h"
+
+#define CX_DEV_NONE 0
+#define DEVICE_NAME "tiocx"
+#define WIDGET_ID 0
+#define TIOCX_DEBUG 0
+
+#if TIOCX_DEBUG
+#define DBG(fmt...)    printk(KERN_ALERT fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+struct device_attribute dev_attr_cxdev_control;
+
+/**
+ * tiocx_match - Try to match driver id list with device.
+ * @dev: device pointer
+ * @drv: driver pointer
+ *
+ * Returns 1 if match, 0 otherwise.
+ */
+static int tiocx_match(struct device *dev, struct device_driver *drv)
+{
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+	struct cx_drv *cx_drv = to_cx_driver(drv);
+	const struct cx_device_id *ids = cx_drv->id_table;
+
+	if (!ids)
+		return 0;
+
+	while (ids->part_num) {
+		if (ids->part_num == cx_dev->cx_id.part_num)
+			return 1;
+		ids++;
+	}
+	return 0;
+
+}
+
+static int tiocx_hotplug(struct device *dev, char **envp, int num_envp,
+			 char *buffer, int buffer_size)
+{
+	return -ENODEV;
+}
+
+static void tiocx_bus_release(struct device *dev)
+{
+	kfree(to_cx_dev(dev));
+}
+
+struct bus_type tiocx_bus_type = {
+	.name = "tiocx",
+	.match = tiocx_match,
+	.hotplug = tiocx_hotplug,
+};
+
+/**
+ * cx_device_match - Find cx_device in the id table.
+ * @ids: id table from driver
+ * @cx_device: part/mfg id for the device
+ *
+ */
+static const struct cx_device_id *cx_device_match(const struct cx_device_id
+						  *ids,
+						  struct cx_dev *cx_device)
+{
+	/*
+	 * NOTES: We may want to check for CX_ANY_ID too.
+	 *        Do we want to match against nasid too?
+	 *        CX_DEV_NONE == 0, if the driver tries to register for
+	 *        part/mfg == 0 we should return no-match (NULL) here.
+	 */
+	while (ids->part_num && ids->mfg_num) {
+		if (ids->part_num == cx_device->cx_id.part_num &&
+		    ids->mfg_num == cx_device->cx_id.mfg_num)
+			return ids;
+		ids++;
+	}
+
+	return NULL;
+}
+
+/**
+ * cx_device_probe - Look for matching device.
+ *			Call driver probe routine if found.
+ * @cx_driver: driver table (cx_drv struct) from driver
+ * @cx_device: part/mfg id for the device
+ */
+static int cx_device_probe(struct device *dev)
+{
+	const struct cx_device_id *id;
+	struct cx_drv *cx_drv = to_cx_driver(dev->driver);
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+	int error = 0;
+
+	if (!cx_dev->driver && cx_drv->probe) {
+		id = cx_device_match(cx_drv->id_table, cx_dev);
+		if (id) {
+			if ((error = cx_drv->probe(cx_dev, id)) < 0)
+				return error;
+			else
+				cx_dev->driver = cx_drv;
+		}
+	}
+
+	return error;
+}
+
+/**
+ * cx_driver_remove - Remove driver from device struct.
+ * @dev: device
+ */
+static int cx_driver_remove(struct device *dev)
+{
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+	struct cx_drv *cx_drv = cx_dev->driver;
+	if (cx_drv->remove)
+		cx_drv->remove(cx_dev);
+	cx_dev->driver = NULL;
+	return 0;
+}
+
+/**
+ * cx_driver_register - Register the driver.
+ * @cx_driver: driver table (cx_drv struct) from driver
+ * 
+ * Called from the driver init routine to register a driver.
+ * The cx_drv struct contains the driver name, a pointer to
+ * a table of part/mfg numbers and a pointer to the driver's
+ * probe/attach routine.
+ */
+int cx_driver_register(struct cx_drv *cx_driver)
+{
+	cx_driver->driver.name = cx_driver->name;
+	cx_driver->driver.bus = &tiocx_bus_type;
+	cx_driver->driver.probe = cx_device_probe;
+	cx_driver->driver.remove = cx_driver_remove;
+
+	return driver_register(&cx_driver->driver);
+}
+
+/**
+ * cx_driver_unregister - Unregister the driver.
+ * @cx_driver: driver table (cx_drv struct) from driver
+ */
+int cx_driver_unregister(struct cx_drv *cx_driver)
+{
+	driver_unregister(&cx_driver->driver);
+	return 0;
+}
+
+/**
+ * cx_device_register - Register a device.
+ * @nasid: device's nasid
+ * @part_num: device's part number
+ * @mfg_num: device's manufacturer number
+ * @hubdev: hub info associated with this device
+ *
+ */
+int
+cx_device_register(nasid_t nasid, int part_num, int mfg_num,
+		   struct hubdev_info *hubdev)
+{
+	struct cx_dev *cx_dev;
+
+	cx_dev = kcalloc(1, sizeof(struct cx_dev), GFP_KERNEL);
+	DBG("cx_dev= 0x%p\n", cx_dev);
+	if (cx_dev == NULL)
+		return -ENOMEM;
+
+	cx_dev->cx_id.part_num = part_num;
+	cx_dev->cx_id.mfg_num = mfg_num;
+	cx_dev->cx_id.nasid = nasid;
+	cx_dev->hubdev = hubdev;
+
+	cx_dev->dev.parent = NULL;
+	cx_dev->dev.bus = &tiocx_bus_type;
+	cx_dev->dev.release = tiocx_bus_release;
+	snprintf(cx_dev->dev.bus_id, BUS_ID_SIZE, "%d.0x%x",
+		 cx_dev->cx_id.nasid, cx_dev->cx_id.part_num);
+	device_register(&cx_dev->dev);
+	get_device(&cx_dev->dev);
+
+	device_create_file(&cx_dev->dev, &dev_attr_cxdev_control);
+
+	return 0;
+}
+
+/**
+ * cx_device_unregister - Unregister a device.
+ * @cx_dev: part/mfg id for the device
+ */
+int cx_device_unregister(struct cx_dev *cx_dev)
+{
+	put_device(&cx_dev->dev);
+	device_unregister(&cx_dev->dev);
+	return 0;
+}
+
+/**
+ * cx_device_reload - Reload the device.
+ * @nasid: device's nasid
+ * @part_num: device's part number
+ * @mfg_num: device's manufacturer number
+ *
+ * Remove the device associated with 'nasid' from device list and then
+ * call device-register with the given part/mfg numbers.
+ */
+static int cx_device_reload(struct cx_dev *cx_dev)
+{
+	device_remove_file(&cx_dev->dev, &dev_attr_cxdev_control);
+	cx_device_unregister(cx_dev);
+	return cx_device_register(cx_dev->cx_id.nasid, cx_dev->cx_id.part_num,
+				  cx_dev->cx_id.mfg_num, cx_dev->hubdev);
+}
+
+static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget,
+					u64 sn_irq_info,
+					int req_irq, nasid_t req_nasid,
+					int req_slice)
+{
+	struct ia64_sal_retval rv;
+	rv.status = 0;
+	rv.v0 = 0;
+
+	ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
+				SAL_INTR_ALLOC, nasid,
+				widget, sn_irq_info, req_irq,
+				req_nasid, req_slice);
+	return rv.status;
+}
+
+static inline void tiocx_intr_free(nasid_t nasid, int widget,
+				   struct sn_irq_info *sn_irq_info)
+{
+	struct ia64_sal_retval rv;
+	rv.status = 0;
+	rv.v0 = 0;
+
+	ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
+				SAL_INTR_FREE, nasid,
+				widget, sn_irq_info->irq_irq,
+				sn_irq_info->irq_cookie, 0, 0);
+}
+
+struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq,
+				    nasid_t req_nasid, int slice)
+{
+	struct sn_irq_info *sn_irq_info;
+	int status;
+	int sn_irq_size = sizeof(struct sn_irq_info);
+
+	if ((nasid & 1) == 0)
+		return NULL;
+
+	sn_irq_info = kmalloc(sn_irq_size, GFP_KERNEL);
+	if (sn_irq_info == NULL)
+		return NULL;
+
+	memset(sn_irq_info, 0x0, sn_irq_size);
+
+	status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq,
+				  req_nasid, slice);
+	if (status) {
+		kfree(sn_irq_info);
+		return NULL;
+	} else {
+		return sn_irq_info;
+	}
+}
+
+void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
+{
+	uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
+	nasid_t nasid = NASID_GET(bridge);
+	int widget;
+
+	if (nasid & 1) {
+		widget = TIO_SWIN_WIDGETNUM(bridge);
+		tiocx_intr_free(nasid, widget, sn_irq_info);
+		kfree(sn_irq_info);
+	}
+}
+
+uint64_t tiocx_dma_addr(uint64_t addr)
+{
+	return PHYS_TO_TIODMA(addr);
+}
+
+uint64_t tiocx_swin_base(int nasid)
+{
+	return TIO_SWIN_BASE(nasid, TIOCX_CORELET);
+}
+
+EXPORT_SYMBOL(cx_driver_register);
+EXPORT_SYMBOL(cx_driver_unregister);
+EXPORT_SYMBOL(cx_device_register);
+EXPORT_SYMBOL(cx_device_unregister);
+EXPORT_SYMBOL(tiocx_irq_alloc);
+EXPORT_SYMBOL(tiocx_irq_free);
+EXPORT_SYMBOL(tiocx_bus_type);
+EXPORT_SYMBOL(tiocx_dma_addr);
+EXPORT_SYMBOL(tiocx_swin_base);
+
+static void tio_conveyor_set(nasid_t nasid, int enable_flag)
+{
+	uint64_t ice_frz;
+	uint64_t disable_cb = (1ull << 61);
+
+	if (!(nasid & 1))
+		return;
+
+	ice_frz = REMOTE_HUB_L(nasid, TIO_ICE_FRZ_CFG);
+	if (enable_flag) {
+		if (!(ice_frz & disable_cb))	/* already enabled */
+			return;
+		ice_frz &= ~disable_cb;
+	} else {
+		if (ice_frz & disable_cb)	/* already disabled */
+			return;
+		ice_frz |= disable_cb;
+	}
+	DBG(KERN_ALERT "TIO_ICE_FRZ_CFG= 0x%lx\n", ice_frz);
+	REMOTE_HUB_S(nasid, TIO_ICE_FRZ_CFG, ice_frz);
+}
+
+#define tio_conveyor_enable(nasid) tio_conveyor_set(nasid, 1)
+#define tio_conveyor_disable(nasid) tio_conveyor_set(nasid, 0)
+
+static void tio_corelet_reset(nasid_t nasid, int corelet)
+{
+	if (!(nasid & 1))
+		return;
+
+	REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 1 << corelet);
+	udelay(2000);
+	REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 0);
+	udelay(2000);
+}
+
+static int tiocx_btchar_get(int nasid)
+{
+	moduleid_t module_id;
+	geoid_t geoid;
+	int cnodeid;
+
+	cnodeid = nasid_to_cnodeid(nasid);
+	geoid = cnodeid_get_geoid(cnodeid);
+	module_id = geo_module(geoid);
+	return MODULE_GET_BTCHAR(module_id);
+}
+
+static int is_fpga_brick(int nasid)
+{
+	switch (tiocx_btchar_get(nasid)) {
+	case L1_BRICKTYPE_SA:
+	case L1_BRICKTYPE_ATHENA:
+		return 1;
+	}
+	return 0;
+}
+
+static int bitstream_loaded(nasid_t nasid)
+{
+	uint64_t cx_credits;
+
+	cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
+	cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
+	DBG("cx_credits= 0x%lx\n", cx_credits);
+
+	return (cx_credits == 0xf) ? 1 : 0;
+}
+
+static int tiocx_reload(struct cx_dev *cx_dev)
+{
+	int part_num = CX_DEV_NONE;
+	int mfg_num = CX_DEV_NONE;
+	nasid_t nasid = cx_dev->cx_id.nasid;
+
+	if (bitstream_loaded(nasid)) {
+		uint64_t cx_id;
+
+		cx_id =
+		    *(volatile int32_t *)(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
+					  WIDGET_ID);
+		part_num = XWIDGET_PART_NUM(cx_id);
+		mfg_num = XWIDGET_MFG_NUM(cx_id);
+		DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
+		/* just ignore it if it's a CE */
+		if (part_num == TIO_CE_ASIC_PARTNUM)
+			return 0;
+	}
+
+	cx_dev->cx_id.part_num = part_num;
+	cx_dev->cx_id.mfg_num = mfg_num;
+
+	/*
+	 * Delete old device and register the new one.  It's ok if
+	 * part_num/mfg_num == CX_DEV_NONE.  We want to register
+	 * devices in the table even if a bitstream isn't loaded.
+	 * That allows use to see that a bitstream isn't loaded via
+	 * TIOCX_IOCTL_DEV_LIST.
+	 */
+	return cx_device_reload(cx_dev);
+}
+
+static ssize_t show_cxdev_control(struct device *dev, char *buf)
+{
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+
+	return sprintf(buf, "0x%x 0x%x 0x%x %d\n",
+		       cx_dev->cx_id.nasid,
+		       cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
+		       tiocx_btchar_get(cx_dev->cx_id.nasid));
+}
+
+static ssize_t store_cxdev_control(struct device *dev, const char *buf,
+				   size_t count)
+{
+	int n;
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (count <= 0)
+		return 0;
+
+	n = simple_strtoul(buf, NULL, 0);
+
+	switch (n) {
+	case 1:
+		tiocx_reload(cx_dev);
+		break;
+	case 3:
+		tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
+		break;
+	default:
+		break;
+	}
+
+	return count;
+}
+
+DEVICE_ATTR(cxdev_control, 0644, show_cxdev_control, store_cxdev_control);
+
+static int __init tiocx_init(void)
+{
+	cnodeid_t cnodeid;
+	int found_tiocx_device = 0;
+
+	bus_register(&tiocx_bus_type);
+
+	for (cnodeid = 0; cnodeid < MAX_COMPACT_NODES; cnodeid++) {
+		nasid_t nasid;
+
+		if ((nasid = cnodeid_to_nasid(cnodeid)) < 0)
+			break;	/* No more nasids .. bail out of loop */
+
+		if ((nasid & 0x1) && is_fpga_brick(nasid)) {
+			struct hubdev_info *hubdev;
+			struct xwidget_info *widgetp;
+
+			DBG("Found TIO at nasid 0x%x\n", nasid);
+
+			hubdev =
+			    (struct hubdev_info *)(NODEPDA(cnodeid)->pdinfo);
+
+			widgetp = &hubdev->hdi_xwidget_info[TIOCX_CORELET];
+
+			/* The CE hangs off of the CX port but is not an FPGA */
+			if (widgetp->xwi_hwid.part_num == TIO_CE_ASIC_PARTNUM)
+				continue;
+
+			tio_corelet_reset(nasid, TIOCX_CORELET);
+			tio_conveyor_enable(nasid);
+
+			if (cx_device_register
+			    (nasid, widgetp->xwi_hwid.part_num,
+			     widgetp->xwi_hwid.mfg_num, hubdev) < 0)
+				return -ENXIO;
+			else
+				found_tiocx_device++;
+		}
+	}
+
+	/* It's ok if we find zero devices. */
+	DBG("found_tiocx_device= %d\n", found_tiocx_device);
+
+	return 0;
+}
+
+static void __exit tiocx_exit(void)
+{
+	struct device *dev;
+	struct device *tdev;
+
+	DBG("tiocx_exit\n");
+
+	/*
+	 * Unregister devices.
+	 */
+	list_for_each_entry_safe(dev, tdev, &tiocx_bus_type.devices.list,
+				 bus_list) {
+		if (dev) {
+			struct cx_dev *cx_dev = to_cx_dev(dev);
+			device_remove_file(dev, &dev_attr_cxdev_control);
+			cx_device_unregister(cx_dev);
+		}
+	}
+
+	bus_unregister(&tiocx_bus_type);
+}
+
+module_init(tiocx_init);
+module_exit(tiocx_exit);
+
+/************************************************************************
+ * Module licensing and description
+ ************************************************************************/
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
+MODULE_DESCRIPTION("TIOCX module");
+MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
new file mode 100644
index 0000000..3be52a3
--- /dev/null
+++ b/arch/ia64/sn/kernel/xp_main.c
@@ -0,0 +1,289 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition (XP) base.
+ *
+ *	XP provides a base from which its users can interact
+ *	with XPC, yet not be dependent on XPC.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * Target of nofault PIO read.
+ */
+u64 xp_nofault_PIOR_target;
+
+
+/*
+ * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
+ * users of XPC.
+ */
+struct xpc_registration xpc_registrations[XPC_NCHANNELS];
+
+
+/*
+ * Initialize the XPC interface to indicate that XPC isn't loaded.
+ */
+static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
+
+struct xpc_interface xpc_interface = {
+	(void (*)(int)) xpc_notloaded,
+	(void (*)(int)) xpc_notloaded,
+	(enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
+	(enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
+	(enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
+							xpc_notloaded,
+	(void (*)(partid_t, int, void *)) xpc_notloaded,
+	(enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
+};
+
+
+/*
+ * XPC calls this when it (the XPC module) has been loaded.
+ */
+void
+xpc_set_interface(void (*connect)(int),
+		void (*disconnect)(int),
+		enum xpc_retval (*allocate)(partid_t, int, u32, void **),
+		enum xpc_retval (*send)(partid_t, int, void *),
+		enum xpc_retval (*send_notify)(partid_t, int, void *,
+						xpc_notify_func, void *),
+		void (*received)(partid_t, int, void *),
+		enum xpc_retval (*partid_to_nasids)(partid_t, void *))
+{
+	xpc_interface.connect = connect;
+	xpc_interface.disconnect = disconnect;
+	xpc_interface.allocate = allocate;
+	xpc_interface.send = send;
+	xpc_interface.send_notify = send_notify;
+	xpc_interface.received = received;
+	xpc_interface.partid_to_nasids = partid_to_nasids;
+}
+
+
+/*
+ * XPC calls this when it (the XPC module) is being unloaded.
+ */
+void
+xpc_clear_interface(void)
+{
+	xpc_interface.connect = (void (*)(int)) xpc_notloaded;
+	xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
+	xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
+					void **)) xpc_notloaded;
+	xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
+					xpc_notloaded;
+	xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
+				    xpc_notify_func, void *)) xpc_notloaded;
+	xpc_interface.received = (void (*)(partid_t, int, void *))
+					xpc_notloaded;
+	xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
+					xpc_notloaded;
+}
+
+
+/*
+ * Register for automatic establishment of a channel connection whenever
+ * a partition comes up.
+ *
+ * Arguments:
+ *
+ *	ch_number - channel # to register for connection.
+ *	func - function to call for asynchronous notification of channel
+ *	       state changes (i.e., connection, disconnection, error) and
+ *	       the arrival of incoming messages.
+ *      key - pointer to optional user-defined value that gets passed back
+ *	      to the user on any callouts made to func.
+ *	payload_size - size in bytes of the XPC message's payload area which
+ *		       contains a user-defined message. The user should make
+ *		       this large enough to hold their largest message.
+ *	nentries - max #of XPC message entries a message queue can contain.
+ *		   The actual number, which is determined when a connection
+ * 		   is established and may be less then requested, will be
+ *		   passed to the user via the xpcConnected callout.
+ *	assigned_limit - max number of kthreads allowed to be processing
+ * 			 messages (per connection) at any given instant.
+ *	idle_limit - max number of kthreads allowed to be idle at any given
+ * 		     instant.
+ */
+enum xpc_retval
+xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
+		u16 nentries, u32 assigned_limit, u32 idle_limit)
+{
+	struct xpc_registration *registration;
+
+
+	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+	DBUG_ON(payload_size == 0 || nentries == 0);
+	DBUG_ON(func == NULL);
+	DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
+
+	registration = &xpc_registrations[ch_number];
+
+	if (down_interruptible(&registration->sema) != 0) {
+		return xpcInterrupted;
+	}
+
+	/* if XPC_CHANNEL_REGISTERED(ch_number) */
+	if (registration->func != NULL) {
+		up(&registration->sema);
+		return xpcAlreadyRegistered;
+	}
+
+	/* register the channel for connection */
+	registration->msg_size = XPC_MSG_SIZE(payload_size);
+	registration->nentries = nentries;
+	registration->assigned_limit = assigned_limit;
+	registration->idle_limit = idle_limit;
+	registration->key = key;
+	registration->func = func;
+
+	up(&registration->sema);
+
+	xpc_interface.connect(ch_number);
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Remove the registration for automatic connection of the specified channel
+ * when a partition comes up.
+ *
+ * Before returning this xpc_disconnect() will wait for all connections on the
+ * specified channel have been closed/torndown. So the caller can be assured
+ * that they will not be receiving any more callouts from XPC to their
+ * function registered via xpc_connect().
+ *
+ * Arguments:
+ *
+ *	ch_number - channel # to unregister.
+ */
+void
+xpc_disconnect(int ch_number)
+{
+	struct xpc_registration *registration;
+
+
+	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+	registration = &xpc_registrations[ch_number];
+
+	/*
+	 * We've decided not to make this a down_interruptible(), since we
+	 * figured XPC's users will just turn around and call xpc_disconnect()
+	 * again anyways, so we might as well wait, if need be.
+	 */
+	down(&registration->sema);
+
+	/* if !XPC_CHANNEL_REGISTERED(ch_number) */
+	if (registration->func == NULL) {
+		up(&registration->sema);
+		return;
+	}
+
+	/* remove the connection registration for the specified channel */
+	registration->func = NULL;
+	registration->key = NULL;
+	registration->nentries = 0;
+	registration->msg_size = 0;
+	registration->assigned_limit = 0;
+	registration->idle_limit = 0;
+
+	xpc_interface.disconnect(ch_number);
+
+	up(&registration->sema);
+
+	return;
+}
+
+
+int __init
+xp_init(void)
+{
+	int ret, ch_number;
+	u64 func_addr = *(u64 *) xp_nofault_PIOR;
+	u64 err_func_addr = *(u64 *) xp_error_PIOR;
+
+
+	if (!ia64_platform_is("sn2")) {
+		return -ENODEV;
+	}
+
+	/*
+	 * Register a nofault code region which performs a cross-partition
+	 * PIO read. If the PIO read times out, the MCA handler will consume
+	 * the error and return to a kernel-provided instruction to indicate
+	 * an error. This PIO read exists because it is guaranteed to timeout
+	 * if the destination is down (AMO operations do not timeout on at
+	 * least some CPUs on Shubs <= v1.2, which unfortunately we have to
+	 * work around).
+	 */
+	if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
+						err_func_addr, 1, 1)) != 0) {
+		printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
+			ret);
+	}
+	/*
+	 * Setup the nofault PIO read target. (There is no special reason why
+	 * SH_IPI_ACCESS was selected.)
+	 */
+	if (is_shub2()) {
+		xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
+	} else {
+		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
+	}
+
+	/* initialize the connection registration semaphores */
+	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
+		sema_init(&xpc_registrations[ch_number].sema, 1);  /* mutex */
+	}
+
+	return 0;
+}
+module_init(xp_init);
+
+
+void __exit
+xp_exit(void)
+{
+	u64 func_addr = *(u64 *) xp_nofault_PIOR;
+	u64 err_func_addr = *(u64 *) xp_error_PIOR;
+
+
+	/* unregister the PIO read nofault code region */
+	(void) sn_register_nofault_code(func_addr, err_func_addr,
+					err_func_addr, 1, 0);
+}
+module_exit(xp_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition (XP) base");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(xp_nofault_PIOR);
+EXPORT_SYMBOL(xp_nofault_PIOR_target);
+EXPORT_SYMBOL(xpc_registrations);
+EXPORT_SYMBOL(xpc_interface);
+EXPORT_SYMBOL(xpc_clear_interface);
+EXPORT_SYMBOL(xpc_set_interface);
+EXPORT_SYMBOL(xpc_connect);
+EXPORT_SYMBOL(xpc_disconnect);
+
diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
new file mode 100644
index 0000000..b772543
--- /dev/null
+++ b/arch/ia64/sn/kernel/xp_nofault.S
@@ -0,0 +1,31 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * The xp_nofault_PIOR function takes a pointer to a remote PIO register
+ * and attempts to load and consume a value from it.  This function
+ * will be registered as a nofault code block.  In the event that the
+ * PIO read fails, the MCA handler will force the error to look
+ * corrected and vector to the xp_error_PIOR which will return an error.
+ *
+ *	extern int xp_nofault_PIOR(void *remote_register);
+ */
+
+	.global xp_nofault_PIOR
+xp_nofault_PIOR:
+	mov	r8=r0			// Stage a success return value
+	ld8.acq	r9=[r32];;		// PIO Read the specified register
+	adds	r9=1,r9			// Add to force a consume
+	br.ret.sptk.many b0;;		// Return success
+
+	.global xp_error_PIOR
+xp_error_PIOR:
+	mov	r8=1			// Return value of 1
+	br.ret.sptk.many b0;;		// Return failure
+
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h
new file mode 100644
index 0000000..1a0aed8
--- /dev/null
+++ b/arch/ia64/sn/kernel/xpc.h
@@ -0,0 +1,991 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) structures and macros.
+ */
+
+#ifndef _IA64_SN_KERNEL_XPC_H
+#define _IA64_SN_KERNEL_XPC_H
+
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/device.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/mspec.h>
+#include <asm/sn/shub_mmr.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * XPC Version numbers consist of a major and minor number. XPC can always
+ * talk to versions with same major #, and never talk to versions with a
+ * different major #.
+ */
+#define _XPC_VERSION(_maj, _min)	(((_maj) << 4) | ((_min) & 0xf))
+#define XPC_VERSION_MAJOR(_v)		((_v) >> 4)
+#define XPC_VERSION_MINOR(_v)		((_v) & 0xf)
+
+
+/*
+ * The next macros define word or bit representations for given
+ * C-brick nasid in either the SAL provided bit array representing
+ * nasids in the partition/machine or the AMO_t array used for
+ * inter-partition initiation communications.
+ *
+ * For SN2 machines, C-Bricks are alway even numbered NASIDs.  As
+ * such, some space will be saved by insisting that nasid information
+ * passed from SAL always be packed for C-Bricks and the
+ * cross-partition interrupts use the same packing scheme.
+ */
+#define XPC_NASID_W_INDEX(_n)	(((_n) / 64) / 2)
+#define XPC_NASID_B_INDEX(_n)	(((_n) / 2) & (64 - 1))
+#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
+				    (1UL << XPC_NASID_B_INDEX(_n)))
+#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
+
+#define XPC_HB_DEFAULT_INTERVAL		5	/* incr HB every x secs */
+#define XPC_HB_CHECK_DEFAULT_TIMEOUT	20	/* check HB every x secs */
+
+/* define the process name of HB checker and the CPU it is pinned to */
+#define XPC_HB_CHECK_THREAD_NAME	"xpc_hb"
+#define XPC_HB_CHECK_CPU		0
+
+/* define the process name of the discovery thread */
+#define XPC_DISCOVERY_THREAD_NAME	"xpc_discovery"
+
+
+#define XPC_HB_ALLOWED(_p, _v)	((_v)->heartbeating_to_mask & (1UL << (_p)))
+#define XPC_ALLOW_HB(_p, _v)	(_v)->heartbeating_to_mask |= (1UL << (_p))
+#define XPC_DISALLOW_HB(_p, _v)	(_v)->heartbeating_to_mask &= (~(1UL << (_p)))
+
+
+/*
+ * Reserved Page provided by SAL.
+ *
+ * SAL provides one page per partition of reserved memory.  When SAL
+ * initialization is complete, SAL_signature, SAL_version, partid,
+ * part_nasids, and mach_nasids are set.
+ *
+ * Note: Until vars_pa is set, the partition XPC code has not been initialized.
+ */
+struct xpc_rsvd_page {
+	u64 SAL_signature;	/* SAL unique signature */
+	u64 SAL_version;	/* SAL specified version */
+	u8 partid;		/* partition ID from SAL */
+	u8 version;
+	u8 pad[6];		/* pad to u64 align */
+	u64 vars_pa;
+	u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
+	u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
+};
+#define XPC_RP_VERSION _XPC_VERSION(1,0) /* version 1.0 of the reserved page */
+
+#define XPC_RSVD_PAGE_ALIGNED_SIZE \
+			(L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page)))
+
+
+/*
+ * Define the structures by which XPC variables can be exported to other
+ * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
+ */
+
+/*
+ * The following structure describes the partition generic variables
+ * needed by other partitions in order to properly initialize.
+ *
+ * struct xpc_vars version number also applies to struct xpc_vars_part.
+ * Changes to either structure and/or related functionality should be
+ * reflected by incrementing either the major or minor version numbers
+ * of struct xpc_vars.
+ */
+struct xpc_vars {
+	u8 version;
+	u64 heartbeat;
+	u64 heartbeating_to_mask;
+	u64 kdb_status;		/* 0 = machine running */
+	int act_nasid;
+	int act_phys_cpuid;
+	u64 vars_part_pa;
+	u64 amos_page_pa;	/* paddr of page of AMOs from MSPEC driver */
+	AMO_t *amos_page;	/* vaddr of page of AMOs from MSPEC driver */
+	AMO_t *act_amos;	/* pointer to the first activation AMO */
+};
+#define XPC_V_VERSION _XPC_VERSION(3,0) /* version 3.0 of the cross vars */
+
+#define XPC_VARS_ALIGNED_SIZE  (L1_CACHE_ALIGN(sizeof(struct xpc_vars)))
+
+/*
+ * The following structure describes the per partition specific variables.
+ *
+ * An array of these structures, one per partition, will be defined. As a
+ * partition becomes active XPC will copy the array entry corresponding to
+ * itself from that partition. It is desirable that the size of this
+ * structure evenly divide into a cacheline, such that none of the entries
+ * in this array crosses a cacheline boundary. As it is now, each entry
+ * occupies half a cacheline.
+ */
+struct xpc_vars_part {
+	u64 magic;
+
+	u64 openclose_args_pa;	/* physical address of open and close args */
+	u64 GPs_pa;		/* physical address of Get/Put values */
+
+	u64 IPI_amo_pa;		/* physical address of IPI AMO_t structure */
+	int IPI_nasid;		/* nasid of where to send IPIs */
+	int IPI_phys_cpuid;	/* physical CPU ID of where to send IPIs */
+
+	u8 nchannels;		/* #of defined channels supported */
+
+	u8 reserved[23];	/* pad to a full 64 bytes */
+};
+
+/*
+ * The vars_part MAGIC numbers play a part in the first contact protocol.
+ *
+ * MAGIC1 indicates that the per partition specific variables for a remote
+ * partition have been initialized by this partition.
+ *
+ * MAGIC2 indicates that this partition has pulled the remote partititions
+ * per partition variables that pertain to this partition.
+ */
+#define XPC_VP_MAGIC1	0x0053524156435058L  /* 'XPCVARS\0'L (little endian) */
+#define XPC_VP_MAGIC2	0x0073726176435058L  /* 'XPCvars\0'L (little endian) */
+
+
+
+/*
+ * Functions registered by add_timer() or called by kernel_thread() only
+ * allow for a single 64-bit argument. The following macros can be used to
+ * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
+ * the passed argument.
+ */
+#define XPC_PACK_ARGS(_arg1, _arg2) \
+			((((u64) _arg1) & 0xffffffff) | \
+			((((u64) _arg2) & 0xffffffff) << 32))
+
+#define XPC_UNPACK_ARG1(_args)	(((u64) _args) & 0xffffffff)
+#define XPC_UNPACK_ARG2(_args)	((((u64) _args) >> 32) & 0xffffffff)
+
+
+
+/*
+ * Define a Get/Put value pair (pointers) used with a message queue.
+ */
+struct xpc_gp {
+	s64 get;	/* Get value */
+	s64 put;	/* Put value */
+};
+
+#define XPC_GP_SIZE \
+		L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
+
+
+
+/*
+ * Define a structure that contains arguments associated with opening and
+ * closing a channel.
+ */
+struct xpc_openclose_args {
+	u16 reason;		/* reason why channel is closing */
+	u16 msg_size;		/* sizeof each message entry */
+	u16 remote_nentries;	/* #of message entries in remote msg queue */
+	u16 local_nentries;	/* #of message entries in local msg queue */
+	u64 local_msgqueue_pa;	/* physical address of local message queue */
+};
+
+#define XPC_OPENCLOSE_ARGS_SIZE \
+	      L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
+
+
+
+/* struct xpc_msg flags */
+
+#define	XPC_M_DONE		0x01	/* msg has been received/consumed */
+#define	XPC_M_READY		0x02	/* msg is ready to be sent */
+#define	XPC_M_INTERRUPT		0x04	/* send interrupt when msg consumed */
+
+
+#define XPC_MSG_ADDRESS(_payload) \
+		((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
+
+
+
+/*
+ * Defines notify entry.
+ *
+ * This is used to notify a message's sender that their message was received
+ * and consumed by the intended recipient.
+ */
+struct xpc_notify {
+	struct semaphore sema;		/* notify semaphore */
+	u8 type;			/* type of notification */
+
+	/* the following two fields are only used if type == XPC_N_CALL */
+	xpc_notify_func func;		/* user's notify function */
+	void *key;			/* pointer to user's key */
+};
+
+/* struct xpc_notify type of notification */
+
+#define	XPC_N_CALL		0x01	/* notify function provided by user */
+
+
+
+/*
+ * Define the structure that manages all the stuff required by a channel. In
+ * particular, they are used to manage the messages sent across the channel.
+ *
+ * This structure is private to a partition, and is NOT shared across the
+ * partition boundary.
+ *
+ * There is an array of these structures for each remote partition. It is
+ * allocated at the time a partition becomes active. The array contains one
+ * of these structures for each potential channel connection to that partition.
+ *
+ * Each of these structures manages two message queues (circular buffers).
+ * They are allocated at the time a channel connection is made. One of
+ * these message queues (local_msgqueue) holds the locally created messages
+ * that are destined for the remote partition. The other of these message
+ * queues (remote_msgqueue) is a locally cached copy of the remote partition's
+ * own local_msgqueue.
+ *
+ * The following is a description of the Get/Put pointers used to manage these
+ * two message queues. Consider the local_msgqueue to be on one partition
+ * and the remote_msgqueue to be its cached copy on another partition. A
+ * description of what each of the lettered areas contains is included.
+ *
+ *
+ *                     local_msgqueue      remote_msgqueue
+ *
+ *                        |/////////|      |/////////|
+ *    w_remote_GP.get --> +---------+      |/////////|
+ *                        |    F    |      |/////////|
+ *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
+ *                        |         |      |         |
+ *                        |         |      |    E    |
+ *                        |         |      |         |
+ *                        |         |      +---------+ <-- w_local_GP.get
+ *                        |    B    |      |/////////|
+ *                        |         |      |////D////|
+ *                        |         |      |/////////|
+ *                        |         |      +---------+ <-- w_remote_GP.put
+ *                        |         |      |////C////|
+ *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
+ *                        |         |      |/////////|
+ *                        |    A    |      |/////////|
+ *                        |         |      |/////////|
+ *     w_local_GP.put --> +---------+      |/////////|
+ *                        |/////////|      |/////////|
+ *
+ *
+ *	    ( remote_GP.[get|put] are cached copies of the remote
+ *	      partition's local_GP->[get|put], and thus their values can
+ *	      lag behind their counterparts on the remote partition. )
+ *
+ *
+ *  A - Messages that have been allocated, but have not yet been sent to the
+ *	remote partition.
+ *
+ *  B - Messages that have been sent, but have not yet been acknowledged by the
+ *      remote partition as having been received.
+ *
+ *  C - Area that needs to be prepared for the copying of sent messages, by
+ *	the clearing of the message flags of any previously received messages.
+ *
+ *  D - Area into which sent messages are to be copied from the remote
+ *	partition's local_msgqueue and then delivered to their intended
+ *	recipients. [ To allow for a multi-message copy, another pointer
+ *	(next_msg_to_pull) has been added to keep track of the next message
+ *	number needing to be copied (pulled). It chases after w_remote_GP.put.
+ *	Any messages lying between w_local_GP.get and next_msg_to_pull have
+ *	been copied and are ready to be delivered. ]
+ *
+ *  E - Messages that have been copied and delivered, but have not yet been
+ *	acknowledged by the recipient as having been received.
+ *
+ *  F - Messages that have been acknowledged, but XPC has not yet notified the
+ *	sender that the message was received by its intended recipient.
+ *	This is also an area that needs to be prepared for the allocating of
+ *	new messages, by the clearing of the message flags of the acknowledged
+ *	messages.
+ */
+struct xpc_channel {
+	partid_t partid;		/* ID of remote partition connected */
+	spinlock_t lock;		/* lock for updating this structure */
+	u32 flags;			/* general flags */
+
+	enum xpc_retval reason;		/* reason why channel is disconnect'g */
+	int reason_line;		/* line# disconnect initiated from */
+
+	u16 number;			/* channel # */
+
+	u16 msg_size;			/* sizeof each msg entry */
+	u16 local_nentries;		/* #of msg entries in local msg queue */
+	u16 remote_nentries;		/* #of msg entries in remote msg queue*/
+
+	void *local_msgqueue_base;	/* base address of kmalloc'd space */
+	struct xpc_msg *local_msgqueue;	/* local message queue */
+	void *remote_msgqueue_base;	/* base address of kmalloc'd space */
+	struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */
+					/* local message queue */
+	u64 remote_msgqueue_pa;		/* phys addr of remote partition's */
+					/* local message queue */
+
+	atomic_t references;		/* #of external references to queues */
+
+	atomic_t n_on_msg_allocate_wq;   /* #on msg allocation wait queue */
+	wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
+
+	/* queue of msg senders who want to be notified when msg received */
+
+	atomic_t n_to_notify;		/* #of msg senders to notify */
+	struct xpc_notify *notify_queue;/* notify queue for messages sent */
+
+	xpc_channel_func func;		/* user's channel function */
+	void *key;			/* pointer to user's key */
+
+	struct semaphore msg_to_pull_sema; /* next msg to pull serialization */
+	struct semaphore teardown_sema;    /* wait for teardown completion */
+
+	struct xpc_openclose_args *local_openclose_args; /* args passed on */
+					/* opening or closing of channel */
+
+	/* various flavors of local and remote Get/Put values */
+
+	struct xpc_gp *local_GP;	/* local Get/Put values */
+	struct xpc_gp remote_GP;	/* remote Get/Put values */
+	struct xpc_gp w_local_GP;	/* working local Get/Put values */
+	struct xpc_gp w_remote_GP;	/* working remote Get/Put values */
+	s64 next_msg_to_pull;		/* Put value of next msg to pull */
+
+	/* kthread management related fields */
+
+// >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps
+// >>> allow the assigned limit be unbounded and let the idle limit be dynamic
+// >>> dependent on activity over the last interval of time
+	atomic_t kthreads_assigned;	/* #of kthreads assigned to channel */
+	u32 kthreads_assigned_limit; 	/* limit on #of kthreads assigned */
+	atomic_t kthreads_idle;		/* #of kthreads idle waiting for work */
+	u32 kthreads_idle_limit;	/* limit on #of kthreads idle */
+	atomic_t kthreads_active;	/* #of kthreads actively working */
+	// >>> following field is temporary
+	u32 kthreads_created;		/* total #of kthreads created */
+
+	wait_queue_head_t idle_wq;	/* idle kthread wait queue */
+
+} ____cacheline_aligned;
+
+
+/* struct xpc_channel flags */
+
+#define	XPC_C_WASCONNECTED	0x00000001 /* channel was connected */
+
+#define	XPC_C_ROPENREPLY	0x00000002 /* remote open channel reply */
+#define	XPC_C_OPENREPLY		0x00000004 /* local open channel reply */
+#define	XPC_C_ROPENREQUEST	0x00000008 /* remote open channel request */
+#define	XPC_C_OPENREQUEST	0x00000010 /* local open channel request */
+
+#define	XPC_C_SETUP		0x00000020 /* channel's msgqueues are alloc'd */
+#define	XPC_C_CONNECTCALLOUT	0x00000040 /* channel connected callout made */
+#define	XPC_C_CONNECTED		0x00000080 /* local channel is connected */
+#define	XPC_C_CONNECTING	0x00000100 /* channel is being connected */
+
+#define	XPC_C_RCLOSEREPLY	0x00000200 /* remote close channel reply */
+#define	XPC_C_CLOSEREPLY	0x00000400 /* local close channel reply */
+#define	XPC_C_RCLOSEREQUEST	0x00000800 /* remote close channel request */
+#define	XPC_C_CLOSEREQUEST	0x00001000 /* local close channel request */
+
+#define	XPC_C_DISCONNECTED	0x00002000 /* channel is disconnected */
+#define	XPC_C_DISCONNECTING	0x00004000 /* channel is being disconnected */
+
+
+
+/*
+ * Manages channels on a partition basis. There is one of these structures
+ * for each partition (a partition will never utilize the structure that
+ * represents itself).
+ */
+struct xpc_partition {
+
+	/* XPC HB infrastructure */
+
+	u64 remote_rp_pa;		/* phys addr of partition's rsvd pg */
+	u64 remote_vars_pa;		/* phys addr of partition's vars */
+	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
+	u64 last_heartbeat;		/* HB at last read */
+	u64 remote_amos_page_pa;	/* phys addr of partition's amos page */
+	int remote_act_nasid;		/* active part's act/deact nasid */
+	int remote_act_phys_cpuid;	/* active part's act/deact phys cpuid */
+	u32 act_IRQ_rcvd;		/* IRQs since activation */
+	spinlock_t act_lock;		/* protect updating of act_state */
+	u8 act_state;			/* from XPC HB viewpoint */
+	enum xpc_retval reason;		/* reason partition is deactivating */
+	int reason_line;		/* line# deactivation initiated from */
+	int reactivate_nasid;		/* nasid in partition to reactivate */
+
+
+	/* XPC infrastructure referencing and teardown control */
+
+	u8 setup_state;			/* infrastructure setup state */
+	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
+	atomic_t references;		/* #of references to infrastructure */
+
+
+	/*
+	 * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
+	 * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
+	 * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
+	 * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
+	 */
+
+
+	u8 nchannels;		   /* #of defined channels supported */
+	atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
+	struct xpc_channel *channels;/* array of channel structures */
+
+	void *local_GPs_base;	  /* base address of kmalloc'd space */
+	struct xpc_gp *local_GPs; /* local Get/Put values */
+	void *remote_GPs_base;    /* base address of kmalloc'd space */
+	struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */
+				  /* values */
+	u64 remote_GPs_pa;	  /* phys address of remote partition's local */
+				  /* Get/Put values */
+
+
+	/* fields used to pass args when opening or closing a channel */
+
+	void *local_openclose_args_base;  /* base address of kmalloc'd space */
+	struct xpc_openclose_args *local_openclose_args;  /* local's args */
+	void *remote_openclose_args_base; /* base address of kmalloc'd space */
+	struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
+					  /* args */
+	u64 remote_openclose_args_pa;	  /* phys addr of remote's args */
+
+
+	/* IPI sending, receiving and handling related fields */
+
+	int remote_IPI_nasid;	    /* nasid of where to send IPIs */
+	int remote_IPI_phys_cpuid;  /* phys CPU ID of where to send IPIs */
+	AMO_t *remote_IPI_amo_va;   /* address of remote IPI AMO_t structure */
+
+	AMO_t *local_IPI_amo_va;    /* address of IPI AMO_t structure */
+	u64 local_IPI_amo;	    /* IPI amo flags yet to be handled */
+	char IPI_owner[8];	    /* IPI owner's name */
+	struct timer_list dropped_IPI_timer; /* dropped IPI timer */
+
+	spinlock_t IPI_lock;	    /* IPI handler lock */
+
+
+	/* channel manager related fields */
+
+	atomic_t channel_mgr_requests;	/* #of requests to activate chan mgr */
+	wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
+
+} ____cacheline_aligned;
+
+
+/* struct xpc_partition act_state values (for XPC HB) */
+
+#define	XPC_P_INACTIVE		0x00	/* partition is not active */
+#define XPC_P_ACTIVATION_REQ	0x01	/* created thread to activate */
+#define XPC_P_ACTIVATING	0x02	/* activation thread started */
+#define XPC_P_ACTIVE		0x03	/* xpc_partition_up() was called */
+#define XPC_P_DEACTIVATING	0x04	/* partition deactivation initiated */
+
+
+#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
+			xpc_deactivate_partition(__LINE__, (_p), (_reason))
+
+
+/* struct xpc_partition setup_state values */
+
+#define XPC_P_UNSET		0x00	/* infrastructure was never setup */
+#define XPC_P_SETUP		0x01	/* infrastructure is setup */
+#define XPC_P_WTEARDOWN		0x02	/* waiting to teardown infrastructure */
+#define XPC_P_TORNDOWN		0x03	/* infrastructure is torndown */
+
+
+/*
+ * struct xpc_partition IPI_timer #of seconds to wait before checking for
+ * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
+ * after the IPI was received.
+ */
+#define XPC_P_DROPPED_IPI_WAIT	(0.25 * HZ)
+
+
+#define XPC_PARTID(_p)	((partid_t) ((_p) - &xpc_partitions[0]))
+
+
+
+/* found in xp_main.c */
+extern struct xpc_registration xpc_registrations[];
+
+
+/* >>> found in xpc_main.c only */
+extern struct device *xpc_part;
+extern struct device *xpc_chan;
+extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
+extern void xpc_dropped_IPI_check(struct xpc_partition *);
+extern void xpc_activate_kthreads(struct xpc_channel *, int);
+extern void xpc_create_kthreads(struct xpc_channel *, int);
+extern void xpc_disconnect_wait(int);
+
+
+/* found in xpc_main.c and efi-xpc.c */
+extern void xpc_activate_partition(struct xpc_partition *);
+
+
+/* found in xpc_partition.c */
+extern int xpc_exiting;
+extern int xpc_hb_interval;
+extern int xpc_hb_check_interval;
+extern struct xpc_vars *xpc_vars;
+extern struct xpc_rsvd_page *xpc_rsvd_page;
+extern struct xpc_vars_part *xpc_vars_part;
+extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+extern char xpc_remote_copy_buffer[];
+extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
+extern void xpc_allow_IPI_ops(void);
+extern void xpc_restrict_IPI_ops(void);
+extern int xpc_identify_act_IRQ_sender(void);
+extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
+extern void xpc_mark_partition_inactive(struct xpc_partition *);
+extern void xpc_discovery(void);
+extern void xpc_check_remote_hb(void);
+extern void xpc_deactivate_partition(const int, struct xpc_partition *,
+						enum xpc_retval);
+extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
+
+
+/* found in xpc_channel.c */
+extern void xpc_initiate_connect(int);
+extern void xpc_initiate_disconnect(int);
+extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
+extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
+extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
+						xpc_notify_func, void *);
+extern void xpc_initiate_received(partid_t, int, void *);
+extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
+extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
+extern void xpc_process_channel_activity(struct xpc_partition *);
+extern void xpc_connected_callout(struct xpc_channel *);
+extern void xpc_deliver_msg(struct xpc_channel *);
+extern void xpc_disconnect_channel(const int, struct xpc_channel *,
+					enum xpc_retval, unsigned long *);
+extern void xpc_disconnected_callout(struct xpc_channel *);
+extern void xpc_partition_down(struct xpc_partition *, enum xpc_retval);
+extern void xpc_teardown_infrastructure(struct xpc_partition *);
+
+
+
+static inline void
+xpc_wakeup_channel_mgr(struct xpc_partition *part)
+{
+	if (atomic_inc_return(&part->channel_mgr_requests) == 1) {
+		wake_up(&part->channel_mgr_wq);
+	}
+}
+
+
+
+/*
+ * These next two inlines are used to keep us from tearing down a channel's
+ * msg queues while a thread may be referencing them.
+ */
+static inline void
+xpc_msgqueue_ref(struct xpc_channel *ch)
+{
+	atomic_inc(&ch->references);
+}
+
+static inline void
+xpc_msgqueue_deref(struct xpc_channel *ch)
+{
+	s32 refs = atomic_dec_return(&ch->references);
+
+	DBUG_ON(refs < 0);
+	if (refs == 0) {
+		xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
+	}
+}
+
+
+
+#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
+		xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
+
+
+/*
+ * These two inlines are used to keep us from tearing down a partition's
+ * setup infrastructure while a thread may be referencing it.
+ */
+static inline void
+xpc_part_deref(struct xpc_partition *part)
+{
+	s32 refs = atomic_dec_return(&part->references);
+
+
+	DBUG_ON(refs < 0);
+	if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) {
+		wake_up(&part->teardown_wq);
+	}
+}
+
+static inline int
+xpc_part_ref(struct xpc_partition *part)
+{
+	int setup;
+
+
+	atomic_inc(&part->references);
+	setup = (part->setup_state == XPC_P_SETUP);
+	if (!setup) {
+		xpc_part_deref(part);
+	}
+	return setup;
+}
+
+
+
+/*
+ * The following macro is to be used for the setting of the reason and
+ * reason_line fields in both the struct xpc_channel and struct xpc_partition
+ * structures.
+ */
+#define XPC_SET_REASON(_p, _reason, _line) \
+	{ \
+		(_p)->reason = _reason; \
+		(_p)->reason_line = _line; \
+	}
+
+
+
+/*
+ * The following set of macros and inlines are used for the sending and
+ * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
+ * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
+ * the other that is associated with channel activity (SGI_XPC_NOTIFY).
+ */
+
+static inline u64
+xpc_IPI_receive(AMO_t *amo)
+{
+	return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR);
+}
+
+
+static inline enum xpc_retval
+xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
+{
+	int ret = 0;
+	unsigned long irq_flags;
+
+
+	local_irq_save(irq_flags);
+
+	FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag);
+	sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
+
+	/*
+	 * We must always use the nofault function regardless of whether we
+	 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+	 * didn't, we'd never know that the other partition is down and would
+	 * keep sending IPIs and AMOs to it until the heartbeat times out.
+	 */
+	ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
+				xp_nofault_PIOR_target));
+
+	local_irq_restore(irq_flags);
+
+	return ((ret == 0) ? xpcSuccess : xpcPioReadError);
+}
+
+
+/*
+ * IPIs associated with SGI_XPC_ACTIVATE IRQ.
+ */
+
+/*
+ * Flag the appropriate AMO variable and send an IPI to the specified node.
+ */
+static inline void
+xpc_activate_IRQ_send(u64 amos_page, int from_nasid, int to_nasid,
+			int to_phys_cpuid)
+{
+	int w_index = XPC_NASID_W_INDEX(from_nasid);
+	int b_index = XPC_NASID_B_INDEX(from_nasid);
+	AMO_t *amos = (AMO_t *) __va(amos_page +
+					(XP_MAX_PARTITIONS * sizeof(AMO_t)));
+
+
+	(void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
+				to_phys_cpuid, SGI_XPC_ACTIVATE);
+}
+
+static inline void
+xpc_IPI_send_activate(struct xpc_vars *vars)
+{
+	xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
+				vars->act_nasid, vars->act_phys_cpuid);
+}
+
+static inline void
+xpc_IPI_send_activated(struct xpc_partition *part)
+{
+	xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+			part->remote_act_nasid, part->remote_act_phys_cpuid);
+}
+
+static inline void
+xpc_IPI_send_reactivate(struct xpc_partition *part)
+{
+	xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
+				xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
+}
+
+
+/*
+ * IPIs associated with SGI_XPC_NOTIFY IRQ.
+ */
+
+/*
+ * Send an IPI to the remote partition that is associated with the
+ * specified channel.
+ */
+#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
+		xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
+
+static inline void
+xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
+			unsigned long *irq_flags)
+{
+	struct xpc_partition *part = &xpc_partitions[ch->partid];
+	enum xpc_retval ret;
+
+
+	if (likely(part->act_state != XPC_P_DEACTIVATING)) {
+		ret = xpc_IPI_send(part->remote_IPI_amo_va,
+					(u64) ipi_flag << (ch->number * 8),
+					part->remote_IPI_nasid,
+					part->remote_IPI_phys_cpuid,
+					SGI_XPC_NOTIFY);
+		dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
+			ipi_flag_string, ch->partid, ch->number, ret);
+		if (unlikely(ret != xpcSuccess)) {
+			if (irq_flags != NULL) {
+				spin_unlock_irqrestore(&ch->lock, *irq_flags);
+			}
+			XPC_DEACTIVATE_PARTITION(part, ret);
+			if (irq_flags != NULL) {
+				spin_lock_irqsave(&ch->lock, *irq_flags);
+			}
+		}
+	}
+}
+
+
+/*
+ * Make it look like the remote partition, which is associated with the
+ * specified channel, sent us an IPI. This faked IPI will be handled
+ * by xpc_dropped_IPI_check().
+ */
+#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
+		xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
+
+static inline void
+xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
+				char *ipi_flag_string)
+{
+	struct xpc_partition *part = &xpc_partitions[ch->partid];
+
+
+	FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable),
+			FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8)));
+	dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
+		ipi_flag_string, ch->partid, ch->number);
+}
+
+
+/*
+ * The sending and receiving of IPIs includes the setting of an AMO variable
+ * to indicate the reason the IPI was sent. The 64-bit variable is divided
+ * up into eight bytes, ordered from right to left. Byte zero pertains to
+ * channel 0, byte one to channel 1, and so on. Each byte is described by
+ * the following IPI flags.
+ */
+
+#define	XPC_IPI_CLOSEREQUEST	0x01
+#define	XPC_IPI_CLOSEREPLY	0x02
+#define	XPC_IPI_OPENREQUEST	0x04
+#define	XPC_IPI_OPENREPLY	0x08
+#define	XPC_IPI_MSGREQUEST	0x10
+
+
+/* given an AMO variable and a channel#, get its associated IPI flags */
+#define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
+
+#define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f)
+#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010)
+
+
+static inline void
+xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+	struct xpc_openclose_args *args = ch->local_openclose_args;
+
+
+	args->reason = ch->reason;
+
+	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+	struct xpc_openclose_args *args = ch->local_openclose_args;
+
+
+	args->msg_size = ch->msg_size;
+	args->local_nentries = ch->local_nentries;
+
+	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+	struct xpc_openclose_args *args = ch->local_openclose_args;
+
+
+	args->remote_nentries = ch->remote_nentries;
+	args->local_nentries = ch->local_nentries;
+	args->local_msgqueue_pa = __pa(ch->local_msgqueue);
+
+	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_msgrequest(struct xpc_channel *ch)
+{
+	XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
+}
+
+static inline void
+xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
+{
+	XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
+}
+
+
+/*
+ * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
+ * pages are located in the lowest granule. The lowest granule uses 4k pages
+ * for cached references and an alternate TLB handler to never provide a
+ * cacheable mapping for the entire region. This will prevent speculative
+ * reading of cached copies of our lines from being issued which will cause
+ * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
+ * (XP_MAX_PARTITIONS) AMO variables for message notification (xpc_main.c)
+ * and an additional 16 AMO variables for partition activation (xpc_hb.c).
+ */
+static inline AMO_t *
+xpc_IPI_init(partid_t partid)
+{
+	AMO_t *part_amo = xpc_vars->amos_page + partid;
+
+
+	xpc_IPI_receive(part_amo);
+	return part_amo;
+}
+
+
+
+static inline enum xpc_retval
+xpc_map_bte_errors(bte_result_t error)
+{
+	switch (error) {
+	case BTE_SUCCESS:	return xpcSuccess;
+	case BTEFAIL_DIR:	return xpcBteDirectoryError;
+	case BTEFAIL_POISON:	return xpcBtePoisonError;
+	case BTEFAIL_WERR:	return xpcBteWriteError;
+	case BTEFAIL_ACCESS:	return xpcBteAccessError;
+	case BTEFAIL_PWERR:	return xpcBtePWriteError;
+	case BTEFAIL_PRERR:	return xpcBtePReadError;
+	case BTEFAIL_TOUT:	return xpcBteTimeOutError;
+	case BTEFAIL_XTERR:	return xpcBteXtalkError;
+	case BTEFAIL_NOTAVAIL:	return xpcBteNotAvailable;
+	default:		return xpcBteUnmappedError;
+	}
+}
+
+
+
+static inline void *
+xpc_kmalloc_cacheline_aligned(size_t size, int flags, void **base)
+{
+	/* see if kmalloc will give us cachline aligned memory by default */
+	*base = kmalloc(size, flags);
+	if (*base == NULL) {
+		return NULL;
+	}
+	if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+		return *base;
+	}
+	kfree(*base);
+
+	/* nope, we'll have to do it ourselves */
+	*base = kmalloc(size + L1_CACHE_BYTES, flags);
+	if (*base == NULL) {
+		return NULL;
+	}
+	return (void *) L1_CACHE_ALIGN((u64) *base);
+}
+
+
+/*
+ * Check to see if there is any channel activity to/from the specified
+ * partition.
+ */
+static inline void
+xpc_check_for_channel_activity(struct xpc_partition *part)
+{
+	u64 IPI_amo;
+	unsigned long irq_flags;
+
+
+	IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
+	if (IPI_amo == 0) {
+		return;
+	}
+
+	spin_lock_irqsave(&part->IPI_lock, irq_flags);
+	part->local_IPI_amo |= IPI_amo;
+	spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+
+	dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
+		XPC_PARTID(part), IPI_amo);
+
+	xpc_wakeup_channel_mgr(part);
+}
+
+
+#endif /* _IA64_SN_KERNEL_XPC_H */
+
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
new file mode 100644
index 0000000..0bf6fbc
--- /dev/null
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -0,0 +1,2297 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) channel support.
+ *
+ *	This is the part of XPC that manages the channels and
+ *	sends/receives messages across them to/from other partitions.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/cache.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/sn_sal.h>
+#include "xpc.h"
+
+
+/*
+ * Set up the initial values for the XPartition Communication channels.
+ */
+static void
+xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
+{
+	int ch_number;
+	struct xpc_channel *ch;
+
+
+	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+		ch = &part->channels[ch_number];
+
+		ch->partid = partid;
+		ch->number = ch_number;
+		ch->flags = XPC_C_DISCONNECTED;
+
+		ch->local_GP = &part->local_GPs[ch_number];
+		ch->local_openclose_args =
+					&part->local_openclose_args[ch_number];
+
+		atomic_set(&ch->kthreads_assigned, 0);
+		atomic_set(&ch->kthreads_idle, 0);
+		atomic_set(&ch->kthreads_active, 0);
+
+		atomic_set(&ch->references, 0);
+		atomic_set(&ch->n_to_notify, 0);
+
+		spin_lock_init(&ch->lock);
+		sema_init(&ch->msg_to_pull_sema, 1);	/* mutex */
+
+		atomic_set(&ch->n_on_msg_allocate_wq, 0);
+		init_waitqueue_head(&ch->msg_allocate_wq);
+		init_waitqueue_head(&ch->idle_wq);
+	}
+}
+
+
+/*
+ * Setup the infrastructure necessary to support XPartition Communication
+ * between the specified remote partition and the local one.
+ */
+enum xpc_retval
+xpc_setup_infrastructure(struct xpc_partition *part)
+{
+	int ret;
+	struct timer_list *timer;
+	partid_t partid = XPC_PARTID(part);
+
+
+	/*
+	 * Zero out MOST of the entry for this partition. Only the fields
+	 * starting with `nchannels' will be zeroed. The preceding fields must
+	 * remain `viable' across partition ups and downs, since they may be
+	 * referenced during this memset() operation.
+	 */
+	memset(&part->nchannels, 0, sizeof(struct xpc_partition) -
+				offsetof(struct xpc_partition, nchannels));
+
+	/*
+	 * Allocate all of the channel structures as a contiguous chunk of
+	 * memory.
+	 */
+	part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
+								GFP_KERNEL);
+	if (part->channels == NULL) {
+		dev_err(xpc_chan, "can't get memory for channels\n");
+		return xpcNoMemory;
+	}
+	memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS);
+
+	part->nchannels = XPC_NCHANNELS;
+
+
+	/* allocate all the required GET/PUT values */
+
+	part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+					GFP_KERNEL, &part->local_GPs_base);
+	if (part->local_GPs == NULL) {
+		kfree(part->channels);
+		part->channels = NULL;
+		dev_err(xpc_chan, "can't get memory for local get/put "
+			"values\n");
+		return xpcNoMemory;
+	}
+	memset(part->local_GPs, 0, XPC_GP_SIZE);
+
+	part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+					GFP_KERNEL, &part->remote_GPs_base);
+	if (part->remote_GPs == NULL) {
+		kfree(part->channels);
+		part->channels = NULL;
+		kfree(part->local_GPs_base);
+		part->local_GPs = NULL;
+		dev_err(xpc_chan, "can't get memory for remote get/put "
+			"values\n");
+		return xpcNoMemory;
+	}
+	memset(part->remote_GPs, 0, XPC_GP_SIZE);
+
+
+	/* allocate all the required open and close args */
+
+	part->local_openclose_args = xpc_kmalloc_cacheline_aligned(
+					XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+					&part->local_openclose_args_base);
+	if (part->local_openclose_args == NULL) {
+		kfree(part->channels);
+		part->channels = NULL;
+		kfree(part->local_GPs_base);
+		part->local_GPs = NULL;
+		kfree(part->remote_GPs_base);
+		part->remote_GPs = NULL;
+		dev_err(xpc_chan, "can't get memory for local connect args\n");
+		return xpcNoMemory;
+	}
+	memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
+
+	part->remote_openclose_args = xpc_kmalloc_cacheline_aligned(
+					XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+					&part->remote_openclose_args_base);
+	if (part->remote_openclose_args == NULL) {
+		kfree(part->channels);
+		part->channels = NULL;
+		kfree(part->local_GPs_base);
+		part->local_GPs = NULL;
+		kfree(part->remote_GPs_base);
+		part->remote_GPs = NULL;
+		kfree(part->local_openclose_args_base);
+		part->local_openclose_args = NULL;
+		dev_err(xpc_chan, "can't get memory for remote connect args\n");
+		return xpcNoMemory;
+	}
+	memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
+
+
+	xpc_initialize_channels(part, partid);
+
+	atomic_set(&part->nchannels_active, 0);
+
+
+	/* local_IPI_amo were set to 0 by an earlier memset() */
+
+	/* Initialize this partitions AMO_t structure */
+	part->local_IPI_amo_va = xpc_IPI_init(partid);
+
+	spin_lock_init(&part->IPI_lock);
+
+	atomic_set(&part->channel_mgr_requests, 1);
+	init_waitqueue_head(&part->channel_mgr_wq);
+
+	sprintf(part->IPI_owner, "xpc%02d", partid);
+	ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ,
+				part->IPI_owner, (void *) (u64) partid);
+	if (ret != 0) {
+		kfree(part->channels);
+		part->channels = NULL;
+		kfree(part->local_GPs_base);
+		part->local_GPs = NULL;
+		kfree(part->remote_GPs_base);
+		part->remote_GPs = NULL;
+		kfree(part->local_openclose_args_base);
+		part->local_openclose_args = NULL;
+		kfree(part->remote_openclose_args_base);
+		part->remote_openclose_args = NULL;
+		dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
+			"errno=%d\n", -ret);
+		return xpcLackOfResources;
+	}
+
+	/* Setup a timer to check for dropped IPIs */
+	timer = &part->dropped_IPI_timer;
+	init_timer(timer);
+	timer->function = (void (*)(unsigned long)) xpc_dropped_IPI_check;
+	timer->data = (unsigned long) part;
+	timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;
+	add_timer(timer);
+
+	/*
+	 * With the setting of the partition setup_state to XPC_P_SETUP, we're
+	 * declaring that this partition is ready to go.
+	 */
+	(volatile u8) part->setup_state = XPC_P_SETUP;
+
+
+	/*
+	 * Setup the per partition specific variables required by the
+	 * remote partition to establish channel connections with us.
+	 *
+	 * The setting of the magic # indicates that these per partition
+	 * specific variables are ready to be used.
+	 */
+	xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
+	xpc_vars_part[partid].openclose_args_pa =
+					__pa(part->local_openclose_args);
+	xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
+	xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(smp_processor_id());
+	xpc_vars_part[partid].IPI_phys_cpuid =
+					cpu_physical_id(smp_processor_id());
+	xpc_vars_part[partid].nchannels = part->nchannels;
+	(volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Create a wrapper that hides the underlying mechanism for pulling a cacheline
+ * (or multiple cachelines) from a remote partition.
+ *
+ * src must be a cacheline aligned physical address on the remote partition.
+ * dst must be a cacheline aligned virtual address on this partition.
+ * cnt must be an cacheline sized
+ */
+static enum xpc_retval
+xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
+				const void *src, size_t cnt)
+{
+	bte_result_t bte_ret;
+
+
+	DBUG_ON((u64) src != L1_CACHE_ALIGN((u64) src));
+	DBUG_ON((u64) dst != L1_CACHE_ALIGN((u64) dst));
+	DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
+
+	if (part->act_state == XPC_P_DEACTIVATING) {
+		return part->reason;
+	}
+
+	bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst),
+				(u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL);
+	if (bte_ret == BTE_SUCCESS) {
+		return xpcSuccess;
+	}
+
+	dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",
+		XPC_PARTID(part), bte_ret);
+
+	return xpc_map_bte_errors(bte_ret);
+}
+
+
+/*
+ * Pull the remote per partititon specific variables from the specified
+ * partition.
+ */
+enum xpc_retval
+xpc_pull_remote_vars_part(struct xpc_partition *part)
+{
+	u8 buffer[L1_CACHE_BYTES * 2];
+	struct xpc_vars_part *pulled_entry_cacheline =
+			(struct xpc_vars_part *) L1_CACHE_ALIGN((u64) buffer);
+	struct xpc_vars_part *pulled_entry;
+	u64 remote_entry_cacheline_pa, remote_entry_pa;
+	partid_t partid = XPC_PARTID(part);
+	enum xpc_retval ret;
+
+
+	/* pull the cacheline that contains the variables we're interested in */
+
+	DBUG_ON(part->remote_vars_part_pa !=
+				L1_CACHE_ALIGN(part->remote_vars_part_pa));
+	DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);
+
+	remote_entry_pa = part->remote_vars_part_pa +
+			sn_partition_id * sizeof(struct xpc_vars_part);
+
+	remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
+
+	pulled_entry = (struct xpc_vars_part *) ((u64) pulled_entry_cacheline +
+				(remote_entry_pa & (L1_CACHE_BYTES - 1)));
+
+	ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,
+					(void *) remote_entry_cacheline_pa,
+					L1_CACHE_BYTES);
+	if (ret != xpcSuccess) {
+		dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
+			"partition %d, ret=%d\n", partid, ret);
+		return ret;
+	}
+
+
+	/* see if they've been set up yet */
+
+	if (pulled_entry->magic != XPC_VP_MAGIC1 &&
+				pulled_entry->magic != XPC_VP_MAGIC2) {
+
+		if (pulled_entry->magic != 0) {
+			dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
+				"partition %d has bad magic value (=0x%lx)\n",
+				partid, sn_partition_id, pulled_entry->magic);
+			return xpcBadMagic;
+		}
+
+		/* they've not been initialized yet */
+		return xpcRetry;
+	}
+
+	if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
+
+		/* validate the variables */
+
+		if (pulled_entry->GPs_pa == 0 ||
+				pulled_entry->openclose_args_pa == 0 ||
+					pulled_entry->IPI_amo_pa == 0) {
+
+			dev_err(xpc_chan, "partition %d's XPC vars_part for "
+				"partition %d are not valid\n", partid,
+				sn_partition_id);
+			return xpcInvalidAddress;
+		}
+
+		/* the variables we imported look to be valid */
+
+		part->remote_GPs_pa = pulled_entry->GPs_pa;
+		part->remote_openclose_args_pa =
+					pulled_entry->openclose_args_pa;
+		part->remote_IPI_amo_va =
+				      (AMO_t *) __va(pulled_entry->IPI_amo_pa);
+		part->remote_IPI_nasid = pulled_entry->IPI_nasid;
+		part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
+
+		if (part->nchannels > pulled_entry->nchannels) {
+			part->nchannels = pulled_entry->nchannels;
+		}
+
+		/* let the other side know that we've pulled their variables */
+
+		(volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
+	}
+
+	if (pulled_entry->magic == XPC_VP_MAGIC1) {
+		return xpcRetry;
+	}
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
+ */
+static u64
+xpc_get_IPI_flags(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	u64 IPI_amo;
+	enum xpc_retval ret;
+
+
+	/*
+	 * See if there are any IPI flags to be handled.
+	 */
+
+	spin_lock_irqsave(&part->IPI_lock, irq_flags);
+	if ((IPI_amo = part->local_IPI_amo) != 0) {
+		part->local_IPI_amo = 0;
+	}
+	spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+
+
+	if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
+		ret = xpc_pull_remote_cachelines(part,
+					part->remote_openclose_args,
+					(void *) part->remote_openclose_args_pa,
+					XPC_OPENCLOSE_ARGS_SIZE);
+		if (ret != xpcSuccess) {
+			XPC_DEACTIVATE_PARTITION(part, ret);
+
+			dev_dbg(xpc_chan, "failed to pull openclose args from "
+				"partition %d, ret=%d\n", XPC_PARTID(part),
+				ret);
+
+			/* don't bother processing IPIs anymore */
+			IPI_amo = 0;
+		}
+	}
+
+	if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
+		ret = xpc_pull_remote_cachelines(part, part->remote_GPs,
+						(void *) part->remote_GPs_pa,
+						XPC_GP_SIZE);
+		if (ret != xpcSuccess) {
+			XPC_DEACTIVATE_PARTITION(part, ret);
+
+			dev_dbg(xpc_chan, "failed to pull GPs from partition "
+				"%d, ret=%d\n", XPC_PARTID(part), ret);
+
+			/* don't bother processing IPIs anymore */
+			IPI_amo = 0;
+		}
+	}
+
+	return IPI_amo;
+}
+
+
+/*
+ * Allocate the local message queue and the notify queue.
+ */
+static enum xpc_retval
+xpc_allocate_local_msgqueue(struct xpc_channel *ch)
+{
+	unsigned long irq_flags;
+	int nentries;
+	size_t nbytes;
+
+
+	// >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+	// >>> iterations of the for-loop, bail if set?
+
+	// >>> should we impose a minumum #of entries? like 4 or 8?
+	for (nentries = ch->local_nentries; nentries > 0; nentries--) {
+
+		nbytes = nentries * ch->msg_size;
+		ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+						(GFP_KERNEL | GFP_DMA),
+						&ch->local_msgqueue_base);
+		if (ch->local_msgqueue == NULL) {
+			continue;
+		}
+		memset(ch->local_msgqueue, 0, nbytes);
+
+		nbytes = nentries * sizeof(struct xpc_notify);
+		ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA));
+		if (ch->notify_queue == NULL) {
+			kfree(ch->local_msgqueue_base);
+			ch->local_msgqueue = NULL;
+			continue;
+		}
+		memset(ch->notify_queue, 0, nbytes);
+
+		spin_lock_irqsave(&ch->lock, irq_flags);
+		if (nentries < ch->local_nentries) {
+			dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
+				"partid=%d, channel=%d\n", nentries,
+				ch->local_nentries, ch->partid, ch->number);
+
+			ch->local_nentries = nentries;
+		}
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+		return xpcSuccess;
+	}
+
+	dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
+		"queue, partid=%d, channel=%d\n", ch->partid, ch->number);
+	return xpcNoMemory;
+}
+
+
+/*
+ * Allocate the cached remote message queue.
+ */
+static enum xpc_retval
+xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
+{
+	unsigned long irq_flags;
+	int nentries;
+	size_t nbytes;
+
+
+	DBUG_ON(ch->remote_nentries <= 0);
+
+	// >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+	// >>> iterations of the for-loop, bail if set?
+
+	// >>> should we impose a minumum #of entries? like 4 or 8?
+	for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
+
+		nbytes = nentries * ch->msg_size;
+		ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+						(GFP_KERNEL | GFP_DMA),
+						&ch->remote_msgqueue_base);
+		if (ch->remote_msgqueue == NULL) {
+			continue;
+		}
+		memset(ch->remote_msgqueue, 0, nbytes);
+
+		spin_lock_irqsave(&ch->lock, irq_flags);
+		if (nentries < ch->remote_nentries) {
+			dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
+				"partid=%d, channel=%d\n", nentries,
+				ch->remote_nentries, ch->partid, ch->number);
+
+			ch->remote_nentries = nentries;
+		}
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+		return xpcSuccess;
+	}
+
+	dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
+		"partid=%d, channel=%d\n", ch->partid, ch->number);
+	return xpcNoMemory;
+}
+
+
+/*
+ * Allocate message queues and other stuff associated with a channel.
+ *
+ * Note: Assumes all of the channel sizes are filled in.
+ */
+static enum xpc_retval
+xpc_allocate_msgqueues(struct xpc_channel *ch)
+{
+	unsigned long irq_flags;
+	int i;
+	enum xpc_retval ret;
+
+
+	DBUG_ON(ch->flags & XPC_C_SETUP);
+
+	if ((ret = xpc_allocate_local_msgqueue(ch)) != xpcSuccess) {
+		return ret;
+	}
+
+	if ((ret = xpc_allocate_remote_msgqueue(ch)) != xpcSuccess) {
+		kfree(ch->local_msgqueue_base);
+		ch->local_msgqueue = NULL;
+		kfree(ch->notify_queue);
+		ch->notify_queue = NULL;
+		return ret;
+	}
+
+	for (i = 0; i < ch->local_nentries; i++) {
+		/* use a semaphore as an event wait queue */
+		sema_init(&ch->notify_queue[i].sema, 0);
+	}
+
+	sema_init(&ch->teardown_sema, 0);	/* event wait */
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+	ch->flags |= XPC_C_SETUP;
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Process a connect message from a remote partition.
+ *
+ * Note: xpc_process_connect() is expecting to be called with the
+ * spin_lock_irqsave held and will leave it locked upon return.
+ */
+static void
+xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+	enum xpc_retval ret;
+
+
+	DBUG_ON(!spin_is_locked(&ch->lock));
+
+	if (!(ch->flags & XPC_C_OPENREQUEST) ||
+				!(ch->flags & XPC_C_ROPENREQUEST)) {
+		/* nothing more to do for now */
+		return;
+	}
+	DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
+
+	if (!(ch->flags & XPC_C_SETUP)) {
+		spin_unlock_irqrestore(&ch->lock, *irq_flags);
+		ret = xpc_allocate_msgqueues(ch);
+		spin_lock_irqsave(&ch->lock, *irq_flags);
+
+		if (ret != xpcSuccess) {
+			XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
+		}
+		if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) {
+			return;
+		}
+
+		DBUG_ON(!(ch->flags & XPC_C_SETUP));
+		DBUG_ON(ch->local_msgqueue == NULL);
+		DBUG_ON(ch->remote_msgqueue == NULL);
+	}
+
+	if (!(ch->flags & XPC_C_OPENREPLY)) {
+		ch->flags |= XPC_C_OPENREPLY;
+		xpc_IPI_send_openreply(ch, irq_flags);
+	}
+
+	if (!(ch->flags & XPC_C_ROPENREPLY)) {
+		return;
+	}
+
+	DBUG_ON(ch->remote_msgqueue_pa == 0);
+
+	ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP);	/* clear all else */
+
+	dev_info(xpc_chan, "channel %d to partition %d connected\n",
+		ch->number, ch->partid);
+
+	spin_unlock_irqrestore(&ch->lock, *irq_flags);
+	xpc_create_kthreads(ch, 1);
+	spin_lock_irqsave(&ch->lock, *irq_flags);
+}
+
+
+/*
+ * Free up message queues and other stuff that were allocated for the specified
+ * channel.
+ *
+ * Note: ch->reason and ch->reason_line are left set for debugging purposes,
+ * they're cleared when XPC_C_DISCONNECTED is cleared.
+ */
+static void
+xpc_free_msgqueues(struct xpc_channel *ch)
+{
+	DBUG_ON(!spin_is_locked(&ch->lock));
+	DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
+
+	ch->remote_msgqueue_pa = 0;
+	ch->func = NULL;
+	ch->key = NULL;
+	ch->msg_size = 0;
+	ch->local_nentries = 0;
+	ch->remote_nentries = 0;
+	ch->kthreads_assigned_limit = 0;
+	ch->kthreads_idle_limit = 0;
+
+	ch->local_GP->get = 0;
+	ch->local_GP->put = 0;
+	ch->remote_GP.get = 0;
+	ch->remote_GP.put = 0;
+	ch->w_local_GP.get = 0;
+	ch->w_local_GP.put = 0;
+	ch->w_remote_GP.get = 0;
+	ch->w_remote_GP.put = 0;
+	ch->next_msg_to_pull = 0;
+
+	if (ch->flags & XPC_C_SETUP) {
+		ch->flags &= ~XPC_C_SETUP;
+
+		dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
+			ch->flags, ch->partid, ch->number);
+
+		kfree(ch->local_msgqueue_base);
+		ch->local_msgqueue = NULL;
+		kfree(ch->remote_msgqueue_base);
+		ch->remote_msgqueue = NULL;
+		kfree(ch->notify_queue);
+		ch->notify_queue = NULL;
+
+		/* in case someone is waiting for the teardown to complete */
+		up(&ch->teardown_sema);
+	}
+}
+
+
+/*
+ * spin_lock_irqsave() is expected to be held on entry.
+ */
+static void
+xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+	struct xpc_partition *part = &xpc_partitions[ch->partid];
+	u32 ch_flags = ch->flags;
+
+
+	DBUG_ON(!spin_is_locked(&ch->lock));
+
+	if (!(ch->flags & XPC_C_DISCONNECTING)) {
+		return;
+	}
+
+	DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+
+	/* make sure all activity has settled down first */
+
+	if (atomic_read(&ch->references) > 0) {
+		return;
+	}
+	DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+
+	/* it's now safe to free the channel's message queues */
+
+	xpc_free_msgqueues(ch);
+	DBUG_ON(ch->flags & XPC_C_SETUP);
+
+	if (part->act_state != XPC_P_DEACTIVATING) {
+
+		/* as long as the other side is up do the full protocol */
+
+		if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+			return;
+		}
+
+		if (!(ch->flags & XPC_C_CLOSEREPLY)) {
+			ch->flags |= XPC_C_CLOSEREPLY;
+			xpc_IPI_send_closereply(ch, irq_flags);
+		}
+
+		if (!(ch->flags & XPC_C_RCLOSEREPLY)) {
+			return;
+		}
+	}
+
+	/* both sides are disconnected now */
+
+	ch->flags = XPC_C_DISCONNECTED;	/* clear all flags, but this one */
+
+	atomic_dec(&part->nchannels_active);
+
+	if (ch_flags & XPC_C_WASCONNECTED) {
+		dev_info(xpc_chan, "channel %d to partition %d disconnected, "
+			"reason=%d\n", ch->number, ch->partid, ch->reason);
+	}
+}
+
+
+/*
+ * Process a change in the channel's remote connection state.
+ */
+static void
+xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
+				u8 IPI_flags)
+{
+	unsigned long irq_flags;
+	struct xpc_openclose_args *args =
+				&part->remote_openclose_args[ch_number];
+	struct xpc_channel *ch = &part->channels[ch_number];
+	enum xpc_retval reason;
+
+
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+
+
+	if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
+
+		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
+			"from partid=%d, channel=%d\n", args->reason,
+			ch->partid, ch->number);
+
+		/*
+		 * If RCLOSEREQUEST is set, we're probably waiting for
+		 * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
+		 * with this RCLOSEQREUQEST in the IPI_flags.
+		 */
+
+		if (ch->flags & XPC_C_RCLOSEREQUEST) {
+			DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
+			DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+			DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
+			DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
+
+			DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
+			IPI_flags &= ~XPC_IPI_CLOSEREPLY;
+			ch->flags |= XPC_C_RCLOSEREPLY;
+
+			/* both sides have finished disconnecting */
+			xpc_process_disconnect(ch, &irq_flags);
+		}
+
+		if (ch->flags & XPC_C_DISCONNECTED) {
+			// >>> explain this section
+
+			if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
+				DBUG_ON(part->act_state !=
+							XPC_P_DEACTIVATING);
+				spin_unlock_irqrestore(&ch->lock, irq_flags);
+				return;
+			}
+
+			XPC_SET_REASON(ch, 0, 0);
+			ch->flags &= ~XPC_C_DISCONNECTED;
+
+			atomic_inc(&part->nchannels_active);
+			ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
+		}
+
+		IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
+
+		/*
+		 * The meaningful CLOSEREQUEST connection state fields are:
+		 *      reason = reason connection is to be closed
+		 */
+
+		ch->flags |= XPC_C_RCLOSEREQUEST;
+
+		if (!(ch->flags & XPC_C_DISCONNECTING)) {
+			reason = args->reason;
+			if (reason <= xpcSuccess || reason > xpcUnknownReason) {
+				reason = xpcUnknownReason;
+			} else if (reason == xpcUnregistering) {
+				reason = xpcOtherUnregistering;
+			}
+
+			XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+		} else {
+			xpc_process_disconnect(ch, &irq_flags);
+		}
+	}
+
+
+	if (IPI_flags & XPC_IPI_CLOSEREPLY) {
+
+		dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
+			" channel=%d\n", ch->partid, ch->number);
+
+		if (ch->flags & XPC_C_DISCONNECTED) {
+			DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
+
+		DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+		DBUG_ON(!(ch->flags & XPC_C_RCLOSEREQUEST));
+
+		ch->flags |= XPC_C_RCLOSEREPLY;
+
+		if (ch->flags & XPC_C_CLOSEREPLY) {
+			/* both sides have finished disconnecting */
+			xpc_process_disconnect(ch, &irq_flags);
+		}
+	}
+
+
+	if (IPI_flags & XPC_IPI_OPENREQUEST) {
+
+		dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
+			"local_nentries=%d) received from partid=%d, "
+			"channel=%d\n", args->msg_size, args->local_nentries,
+			ch->partid, ch->number);
+
+		if ((ch->flags & XPC_C_DISCONNECTING) ||
+					part->act_state == XPC_P_DEACTIVATING) {
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
+		DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
+							XPC_C_OPENREQUEST)));
+		DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+					XPC_C_OPENREPLY | XPC_C_CONNECTED));
+
+		/*
+		 * The meaningful OPENREQUEST connection state fields are:
+		 *      msg_size = size of channel's messages in bytes
+		 *      local_nentries = remote partition's local_nentries
+		 */
+		DBUG_ON(args->msg_size == 0);
+		DBUG_ON(args->local_nentries == 0);
+
+		ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
+		ch->remote_nentries = args->local_nentries;
+
+
+		if (ch->flags & XPC_C_OPENREQUEST) {
+			if (args->msg_size != ch->msg_size) {
+				XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+								&irq_flags);
+				spin_unlock_irqrestore(&ch->lock, irq_flags);
+				return;
+			}
+		} else {
+			ch->msg_size = args->msg_size;
+
+			XPC_SET_REASON(ch, 0, 0);
+			ch->flags &= ~XPC_C_DISCONNECTED;
+
+			atomic_inc(&part->nchannels_active);
+		}
+
+		xpc_process_connect(ch, &irq_flags);
+	}
+
+
+	if (IPI_flags & XPC_IPI_OPENREPLY) {
+
+		dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
+			"local_nentries=%d, remote_nentries=%d) received from "
+			"partid=%d, channel=%d\n", args->local_msgqueue_pa,
+			args->local_nentries, args->remote_nentries,
+			ch->partid, ch->number);
+
+		if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return;
+		}
+		DBUG_ON(!(ch->flags & XPC_C_OPENREQUEST));
+		DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
+		DBUG_ON(ch->flags & XPC_C_CONNECTED);
+
+		/*
+		 * The meaningful OPENREPLY connection state fields are:
+		 *      local_msgqueue_pa = physical address of remote
+		 *			    partition's local_msgqueue
+		 *      local_nentries = remote partition's local_nentries
+		 *      remote_nentries = remote partition's remote_nentries
+		 */
+		DBUG_ON(args->local_msgqueue_pa == 0);
+		DBUG_ON(args->local_nentries == 0);
+		DBUG_ON(args->remote_nentries == 0);
+
+		ch->flags |= XPC_C_ROPENREPLY;
+		ch->remote_msgqueue_pa = args->local_msgqueue_pa;
+
+		if (args->local_nentries < ch->remote_nentries) {
+			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+				"remote_nentries=%d, old remote_nentries=%d, "
+				"partid=%d, channel=%d\n",
+				args->local_nentries, ch->remote_nentries,
+				ch->partid, ch->number);
+
+			ch->remote_nentries = args->local_nentries;
+		}
+		if (args->remote_nentries < ch->local_nentries) {
+			dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+				"local_nentries=%d, old local_nentries=%d, "
+				"partid=%d, channel=%d\n",
+				args->remote_nentries, ch->local_nentries,
+				ch->partid, ch->number);
+
+			ch->local_nentries = args->remote_nentries;
+		}
+
+		xpc_process_connect(ch, &irq_flags);
+	}
+
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+}
+
+
+/*
+ * Attempt to establish a channel connection to a remote partition.
+ */
+static enum xpc_retval
+xpc_connect_channel(struct xpc_channel *ch)
+{
+	unsigned long irq_flags;
+	struct xpc_registration *registration = &xpc_registrations[ch->number];
+
+
+	if (down_interruptible(&registration->sema) != 0) {
+		return xpcInterrupted;
+	}
+
+	if (!XPC_CHANNEL_REGISTERED(ch->number)) {
+		up(&registration->sema);
+		return xpcUnregistered;
+	}
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+
+	DBUG_ON(ch->flags & XPC_C_CONNECTED);
+	DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
+
+	if (ch->flags & XPC_C_DISCONNECTING) {
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+		up(&registration->sema);
+		return ch->reason;
+	}
+
+
+	/* add info from the channel connect registration to the channel */
+
+	ch->kthreads_assigned_limit = registration->assigned_limit;
+	ch->kthreads_idle_limit = registration->idle_limit;
+	DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+	DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
+	DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
+
+	ch->func = registration->func;
+	DBUG_ON(registration->func == NULL);
+	ch->key = registration->key;
+
+	ch->local_nentries = registration->nentries;
+
+	if (ch->flags & XPC_C_ROPENREQUEST) {
+		if (registration->msg_size != ch->msg_size) {
+			/* the local and remote sides aren't the same */
+
+			/*
+			 * Because XPC_DISCONNECT_CHANNEL() can block we're
+			 * forced to up the registration sema before we unlock
+			 * the channel lock. But that's okay here because we're
+			 * done with the part that required the registration
+			 * sema. XPC_DISCONNECT_CHANNEL() requires that the
+			 * channel lock be locked and will unlock and relock
+			 * the channel lock as needed.
+			 */
+			up(&registration->sema);
+			XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+								&irq_flags);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return xpcUnequalMsgSizes;
+		}
+	} else {
+		ch->msg_size = registration->msg_size;
+
+		XPC_SET_REASON(ch, 0, 0);
+		ch->flags &= ~XPC_C_DISCONNECTED;
+
+		atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
+	}
+
+	up(&registration->sema);
+
+
+	/* initiate the connection */
+
+	ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
+	xpc_IPI_send_openrequest(ch, &irq_flags);
+
+	xpc_process_connect(ch, &irq_flags);
+
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Notify those who wanted to be notified upon delivery of their message.
+ */
+static void
+xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
+{
+	struct xpc_notify *notify;
+	u8 notify_type;
+	s64 get = ch->w_remote_GP.get - 1;
+
+
+	while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
+
+		notify = &ch->notify_queue[get % ch->local_nentries];
+
+		/*
+		 * See if the notify entry indicates it was associated with
+		 * a message who's sender wants to be notified. It is possible
+		 * that it is, but someone else is doing or has done the
+		 * notification.
+		 */
+		notify_type = notify->type;
+		if (notify_type == 0 ||
+				cmpxchg(&notify->type, notify_type, 0) !=
+								notify_type) {
+			continue;
+		}
+
+		DBUG_ON(notify_type != XPC_N_CALL);
+
+		atomic_dec(&ch->n_to_notify);
+
+		if (notify->func != NULL) {
+			dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
+				"msg_number=%ld, partid=%d, channel=%d\n",
+				(void *) notify, get, ch->partid, ch->number);
+
+			notify->func(reason, ch->partid, ch->number,
+								notify->key);
+
+			dev_dbg(xpc_chan, "notify->func() returned, "
+				"notify=0x%p, msg_number=%ld, partid=%d, "
+				"channel=%d\n", (void *) notify, get,
+				ch->partid, ch->number);
+		}
+	}
+}
+
+
+/*
+ * Clear some of the msg flags in the local message queue.
+ */
+static inline void
+xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
+{
+	struct xpc_msg *msg;
+	s64 get;
+
+
+	get = ch->w_remote_GP.get;
+	do {
+		msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+				(get % ch->local_nentries) * ch->msg_size);
+		msg->flags = 0;
+	} while (++get < (volatile s64) ch->remote_GP.get);
+}
+
+
+/*
+ * Clear some of the msg flags in the remote message queue.
+ */
+static inline void
+xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
+{
+	struct xpc_msg *msg;
+	s64 put;
+
+
+	put = ch->w_remote_GP.put;
+	do {
+		msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+				(put % ch->remote_nentries) * ch->msg_size);
+		msg->flags = 0;
+	} while (++put < (volatile s64) ch->remote_GP.put);
+}
+
+
+static void
+xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
+{
+	struct xpc_channel *ch = &part->channels[ch_number];
+	int nmsgs_sent;
+
+
+	ch->remote_GP = part->remote_GPs[ch_number];
+
+
+	/* See what, if anything, has changed for each connected channel */
+
+	xpc_msgqueue_ref(ch);
+
+	if (ch->w_remote_GP.get == ch->remote_GP.get &&
+				ch->w_remote_GP.put == ch->remote_GP.put) {
+		/* nothing changed since GPs were last pulled */
+		xpc_msgqueue_deref(ch);
+		return;
+	}
+
+	if (!(ch->flags & XPC_C_CONNECTED)){
+		xpc_msgqueue_deref(ch);
+		return;
+	}
+
+
+	/*
+	 * First check to see if messages recently sent by us have been
+	 * received by the other side. (The remote GET value will have
+	 * changed since we last looked at it.)
+	 */
+
+	if (ch->w_remote_GP.get != ch->remote_GP.get) {
+
+		/*
+		 * We need to notify any senders that want to be notified
+		 * that their sent messages have been received by their
+		 * intended recipients. We need to do this before updating
+		 * w_remote_GP.get so that we don't allocate the same message
+		 * queue entries prematurely (see xpc_allocate_msg()).
+		 */
+		if (atomic_read(&ch->n_to_notify) > 0) {
+			/*
+			 * Notify senders that messages sent have been
+			 * received and delivered by the other side.
+			 */
+			xpc_notify_senders(ch, xpcMsgDelivered,
+							ch->remote_GP.get);
+		}
+
+		/*
+		 * Clear msg->flags in previously sent messages, so that
+		 * they're ready for xpc_allocate_msg().
+		 */
+		xpc_clear_local_msgqueue_flags(ch);
+
+		(volatile s64) ch->w_remote_GP.get = ch->remote_GP.get;
+
+		dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
+			"channel=%d\n", ch->w_remote_GP.get, ch->partid,
+			ch->number);
+
+		/*
+		 * If anyone was waiting for message queue entries to become
+		 * available, wake them up.
+		 */
+		if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+			wake_up(&ch->msg_allocate_wq);
+		}
+	}
+
+
+	/*
+	 * Now check for newly sent messages by the other side. (The remote
+	 * PUT value will have changed since we last looked at it.)
+	 */
+
+	if (ch->w_remote_GP.put != ch->remote_GP.put) {
+		/*
+		 * Clear msg->flags in previously received messages, so that
+		 * they're ready for xpc_get_deliverable_msg().
+		 */
+		xpc_clear_remote_msgqueue_flags(ch);
+
+		(volatile s64) ch->w_remote_GP.put = ch->remote_GP.put;
+
+		dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
+			"channel=%d\n", ch->w_remote_GP.put, ch->partid,
+			ch->number);
+
+		nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
+		if (nmsgs_sent > 0) {
+			dev_dbg(xpc_chan, "msgs waiting to be copied and "
+				"delivered=%d, partid=%d, channel=%d\n",
+				nmsgs_sent, ch->partid, ch->number);
+
+			if (ch->flags & XPC_C_CONNECTCALLOUT) {
+				xpc_activate_kthreads(ch, nmsgs_sent);
+			}
+		}
+	}
+
+	xpc_msgqueue_deref(ch);
+}
+
+
+void
+xpc_process_channel_activity(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	u64 IPI_amo, IPI_flags;
+	struct xpc_channel *ch;
+	int ch_number;
+
+
+	IPI_amo = xpc_get_IPI_flags(part);
+
+	/*
+	 * Initiate channel connections for registered channels.
+	 *
+	 * For each connected channel that has pending messages activate idle
+	 * kthreads and/or create new kthreads as needed.
+	 */
+
+	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+		ch = &part->channels[ch_number];
+
+
+		/*
+		 * Process any open or close related IPI flags, and then deal
+		 * with connecting or disconnecting the channel as required.
+		 */
+
+		IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
+
+		if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags)) {
+			xpc_process_openclose_IPI(part, ch_number, IPI_flags);
+		}
+
+
+		if (ch->flags & XPC_C_DISCONNECTING) {
+			spin_lock_irqsave(&ch->lock, irq_flags);
+			xpc_process_disconnect(ch, &irq_flags);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			continue;
+		}
+
+		if (part->act_state == XPC_P_DEACTIVATING) {
+			continue;
+		}
+
+		if (!(ch->flags & XPC_C_CONNECTED)) {
+			if (!(ch->flags & XPC_C_OPENREQUEST)) {
+				DBUG_ON(ch->flags & XPC_C_SETUP);
+				(void) xpc_connect_channel(ch);
+			} else {
+				spin_lock_irqsave(&ch->lock, irq_flags);
+				xpc_process_connect(ch, &irq_flags);
+				spin_unlock_irqrestore(&ch->lock, irq_flags);
+			}
+			continue;
+		}
+
+
+		/*
+		 * Process any message related IPI flags, this may involve the
+		 * activation of kthreads to deliver any pending messages sent
+		 * from the other partition.
+		 */
+
+		if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags)) {
+			xpc_process_msg_IPI(part, ch_number);
+		}
+	}
+}
+
+
+/*
+ * XPC's heartbeat code calls this function to inform XPC that a partition has
+ * gone down.  XPC responds by tearing down the XPartition Communication
+ * infrastructure used for the just downed partition.
+ *
+ * XPC's heartbeat code will never call this function and xpc_partition_up()
+ * at the same time. Nor will it ever make multiple calls to either function
+ * at the same time.
+ */
+void
+xpc_partition_down(struct xpc_partition *part, enum xpc_retval reason)
+{
+	unsigned long irq_flags;
+	int ch_number;
+	struct xpc_channel *ch;
+
+
+	dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
+		XPC_PARTID(part), reason);
+
+	if (!xpc_part_ref(part)) {
+		/* infrastructure for this partition isn't currently set up */
+		return;
+	}
+
+
+	/* disconnect all channels associated with the downed partition */
+
+	for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+		ch = &part->channels[ch_number];
+
+
+		xpc_msgqueue_ref(ch);
+		spin_lock_irqsave(&ch->lock, irq_flags);
+
+		XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+		xpc_msgqueue_deref(ch);
+	}
+
+	xpc_wakeup_channel_mgr(part);
+
+	xpc_part_deref(part);
+}
+
+
+/*
+ * Teardown the infrastructure necessary to support XPartition Communication
+ * between the specified remote partition and the local one.
+ */
+void
+xpc_teardown_infrastructure(struct xpc_partition *part)
+{
+	partid_t partid = XPC_PARTID(part);
+
+
+	/*
+	 * We start off by making this partition inaccessible to local
+	 * processes by marking it as no longer setup. Then we make it
+	 * inaccessible to remote processes by clearing the XPC per partition
+	 * specific variable's magic # (which indicates that these variables
+	 * are no longer valid) and by ignoring all XPC notify IPIs sent to
+	 * this partition.
+	 */
+
+	DBUG_ON(atomic_read(&part->nchannels_active) != 0);
+	DBUG_ON(part->setup_state != XPC_P_SETUP);
+	part->setup_state = XPC_P_WTEARDOWN;
+
+	xpc_vars_part[partid].magic = 0;
+
+
+	free_irq(SGI_XPC_NOTIFY, (void *) (u64) partid);
+
+
+	/*
+	 * Before proceding with the teardown we have to wait until all
+	 * existing references cease.
+	 */
+	wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
+
+
+	/* now we can begin tearing down the infrastructure */
+
+	part->setup_state = XPC_P_TORNDOWN;
+
+	/* in case we've still got outstanding timers registered... */
+	del_timer_sync(&part->dropped_IPI_timer);
+
+	kfree(part->remote_openclose_args_base);
+	part->remote_openclose_args = NULL;
+	kfree(part->local_openclose_args_base);
+	part->local_openclose_args = NULL;
+	kfree(part->remote_GPs_base);
+	part->remote_GPs = NULL;
+	kfree(part->local_GPs_base);
+	part->local_GPs = NULL;
+	kfree(part->channels);
+	part->channels = NULL;
+	part->local_IPI_amo_va = NULL;
+}
+
+
+/*
+ * Called by XP at the time of channel connection registration to cause
+ * XPC to establish connections to all currently active partitions.
+ */
+void
+xpc_initiate_connect(int ch_number)
+{
+	partid_t partid;
+	struct xpc_partition *part;
+	struct xpc_channel *ch;
+
+
+	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+		part = &xpc_partitions[partid];
+
+		if (xpc_part_ref(part)) {
+			ch = &part->channels[ch_number];
+
+			if (!(ch->flags & XPC_C_DISCONNECTING)) {
+				DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
+				DBUG_ON(ch->flags & XPC_C_CONNECTED);
+				DBUG_ON(ch->flags & XPC_C_SETUP);
+
+				/*
+				 * Initiate the establishment of a connection
+				 * on the newly registered channel to the
+				 * remote partition.
+				 */
+				xpc_wakeup_channel_mgr(part);
+			}
+
+			xpc_part_deref(part);
+		}
+	}
+}
+
+
+void
+xpc_connected_callout(struct xpc_channel *ch)
+{
+	unsigned long irq_flags;
+
+
+	/* let the registerer know that a connection has been established */
+
+	if (ch->func != NULL) {
+		dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "
+			"partid=%d, channel=%d\n", ch->partid, ch->number);
+
+		ch->func(xpcConnected, ch->partid, ch->number,
+				(void *) (u64) ch->local_nentries, ch->key);
+
+		dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
+			"partid=%d, channel=%d\n", ch->partid, ch->number);
+	}
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+	ch->flags |= XPC_C_CONNECTCALLOUT;
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+}
+
+
+/*
+ * Called by XP at the time of channel connection unregistration to cause
+ * XPC to teardown all current connections for the specified channel.
+ *
+ * Before returning xpc_initiate_disconnect() will wait until all connections
+ * on the specified channel have been closed/torndown. So the caller can be
+ * assured that they will not be receiving any more callouts from XPC to the
+ * function they registered via xpc_connect().
+ *
+ * Arguments:
+ *
+ *	ch_number - channel # to unregister.
+ */
+void
+xpc_initiate_disconnect(int ch_number)
+{
+	unsigned long irq_flags;
+	partid_t partid;
+	struct xpc_partition *part;
+	struct xpc_channel *ch;
+
+
+	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+	/* initiate the channel disconnect for every active partition */
+	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+		part = &xpc_partitions[partid];
+
+		if (xpc_part_ref(part)) {
+			ch = &part->channels[ch_number];
+			xpc_msgqueue_ref(ch);
+
+			spin_lock_irqsave(&ch->lock, irq_flags);
+
+			XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
+								&irq_flags);
+
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+			xpc_msgqueue_deref(ch);
+			xpc_part_deref(part);
+		}
+	}
+
+	xpc_disconnect_wait(ch_number);
+}
+
+
+/*
+ * To disconnect a channel, and reflect it back to all who may be waiting.
+ *
+ * >>> An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+ * >>> xpc_free_msgqueues().
+ *
+ * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
+ */
+void
+xpc_disconnect_channel(const int line, struct xpc_channel *ch,
+			enum xpc_retval reason, unsigned long *irq_flags)
+{
+	u32 flags;
+
+
+	DBUG_ON(!spin_is_locked(&ch->lock));
+
+	if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+		return;
+	}
+	DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
+
+	dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
+		reason, line, ch->partid, ch->number);
+
+	XPC_SET_REASON(ch, reason, line);
+
+	flags = ch->flags;
+	/* some of these may not have been set */
+	ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
+			XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+			XPC_C_CONNECTING | XPC_C_CONNECTED);
+
+	ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
+	xpc_IPI_send_closerequest(ch, irq_flags);
+
+	if (flags & XPC_C_CONNECTED) {
+		ch->flags |= XPC_C_WASCONNECTED;
+	}
+
+	if (atomic_read(&ch->kthreads_idle) > 0) {
+		/* wake all idle kthreads so they can exit */
+		wake_up_all(&ch->idle_wq);
+	}
+
+	spin_unlock_irqrestore(&ch->lock, *irq_flags);
+
+
+	/* wake those waiting to allocate an entry from the local msg queue */
+
+	if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+		wake_up(&ch->msg_allocate_wq);
+	}
+
+	/* wake those waiting for notify completion */
+
+	if (atomic_read(&ch->n_to_notify) > 0) {
+		xpc_notify_senders(ch, reason, ch->w_local_GP.put);
+	}
+
+	spin_lock_irqsave(&ch->lock, *irq_flags);
+}
+
+
+void
+xpc_disconnected_callout(struct xpc_channel *ch)
+{
+	/*
+	 * Let the channel's registerer know that the channel is now
+	 * disconnected. We don't want to do this if the registerer was never
+	 * informed of a connection being made, unless the disconnect was for
+	 * abnormal reasons.
+	 */
+
+	if (ch->func != NULL) {
+		dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
+			"channel=%d\n", ch->reason, ch->partid, ch->number);
+
+		ch->func(ch->reason, ch->partid, ch->number, NULL, ch->key);
+
+		dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
+			"channel=%d\n", ch->reason, ch->partid, ch->number);
+	}
+}
+
+
+/*
+ * Wait for a message entry to become available for the specified channel,
+ * but don't wait any longer than 1 jiffy.
+ */
+static enum xpc_retval
+xpc_allocate_msg_wait(struct xpc_channel *ch)
+{
+	enum xpc_retval ret;
+
+
+	if (ch->flags & XPC_C_DISCONNECTING) {
+		DBUG_ON(ch->reason == xpcInterrupted);  // >>> Is this true?
+		return ch->reason;
+	}
+
+	atomic_inc(&ch->n_on_msg_allocate_wq);
+	ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);
+	atomic_dec(&ch->n_on_msg_allocate_wq);
+
+	if (ch->flags & XPC_C_DISCONNECTING) {
+		ret = ch->reason;
+		DBUG_ON(ch->reason == xpcInterrupted);  // >>> Is this true?
+	} else if (ret == 0) {
+		ret = xpcTimeout;
+	} else {
+		ret = xpcInterrupted;
+	}
+
+	return ret;
+}
+
+
+/*
+ * Allocate an entry for a message from the message queue associated with the
+ * specified channel.
+ */
+static enum xpc_retval
+xpc_allocate_msg(struct xpc_channel *ch, u32 flags,
+			struct xpc_msg **address_of_msg)
+{
+	struct xpc_msg *msg;
+	enum xpc_retval ret;
+	s64 put;
+
+
+	/* this reference will be dropped in xpc_send_msg() */
+	xpc_msgqueue_ref(ch);
+
+	if (ch->flags & XPC_C_DISCONNECTING) {
+		xpc_msgqueue_deref(ch);
+		return ch->reason;
+	}
+	if (!(ch->flags & XPC_C_CONNECTED)) {
+		xpc_msgqueue_deref(ch);
+		return xpcNotConnected;
+	}
+
+
+	/*
+	 * Get the next available message entry from the local message queue.
+	 * If none are available, we'll make sure that we grab the latest
+	 * GP values.
+	 */
+	ret = xpcTimeout;
+
+	while (1) {
+
+		put = (volatile s64) ch->w_local_GP.put;
+		if (put - (volatile s64) ch->w_remote_GP.get <
+							ch->local_nentries) {
+
+			/* There are available message entries. We need to try
+			 * to secure one for ourselves. We'll do this by trying
+			 * to increment w_local_GP.put as long as someone else
+			 * doesn't beat us to it. If they do, we'll have to
+			 * try again.
+		 	 */
+			if (cmpxchg(&ch->w_local_GP.put, put, put + 1) ==
+									put) {
+				/* we got the entry referenced by put */
+				break;
+			}
+			continue;	/* try again */
+		}
+
+
+		/*
+		 * There aren't any available msg entries at this time.
+		 *
+		 * In waiting for a message entry to become available,
+		 * we set a timeout in case the other side is not
+		 * sending completion IPIs. This lets us fake an IPI
+		 * that will cause the IPI handler to fetch the latest
+		 * GP values as if an IPI was sent by the other side.
+		 */
+		if (ret == xpcTimeout) {
+			xpc_IPI_send_local_msgrequest(ch);
+		}
+
+		if (flags & XPC_NOWAIT) {
+			xpc_msgqueue_deref(ch);
+			return xpcNoWait;
+		}
+
+		ret = xpc_allocate_msg_wait(ch);
+		if (ret != xpcInterrupted && ret != xpcTimeout) {
+			xpc_msgqueue_deref(ch);
+			return ret;
+		}
+	}
+
+
+	/* get the message's address and initialize it */
+	msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+				(put % ch->local_nentries) * ch->msg_size);
+
+
+	DBUG_ON(msg->flags != 0);
+	msg->number = put;
+
+	dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
+		"msg_number=%ld, partid=%d, channel=%d\n", put + 1,
+		(void *) msg, msg->number, ch->partid, ch->number);
+
+	*address_of_msg = msg;
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Allocate an entry for a message from the message queue associated with the
+ * specified channel. NOTE that this routine can sleep waiting for a message
+ * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.
+ *
+ * Arguments:
+ *
+ *	partid - ID of partition to which the channel is connected.
+ *	ch_number - channel #.
+ *	flags - see xpc.h for valid flags.
+ *	payload - address of the allocated payload area pointer (filled in on
+ * 	          return) in which the user-defined message is constructed.
+ */
+enum xpc_retval
+xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
+{
+	struct xpc_partition *part = &xpc_partitions[partid];
+	enum xpc_retval ret = xpcUnknownReason;
+	struct xpc_msg *msg;
+
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+
+	*payload = NULL;
+
+	if (xpc_part_ref(part)) {
+		ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);
+		xpc_part_deref(part);
+
+		if (msg != NULL) {
+			*payload = &msg->payload;
+		}
+	}
+
+	return ret;
+}
+
+
+/*
+ * Now we actually send the messages that are ready to be sent by advancing
+ * the local message queue's Put value and then send an IPI to the recipient
+ * partition.
+ */
+static void
+xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)
+{
+	struct xpc_msg *msg;
+	s64 put = initial_put + 1;
+	int send_IPI = 0;
+
+
+	while (1) {
+
+		while (1) {
+			if (put == (volatile s64) ch->w_local_GP.put) {
+				break;
+			}
+
+			msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+			       (put % ch->local_nentries) * ch->msg_size);
+
+			if (!(msg->flags & XPC_M_READY)) {
+				break;
+			}
+
+			put++;
+		}
+
+		if (put == initial_put) {
+			/* nothing's changed */
+			break;
+		}
+
+		if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
+								initial_put) {
+			/* someone else beat us to it */
+			DBUG_ON((volatile s64) ch->local_GP->put < initial_put);
+			break;
+		}
+
+		/* we just set the new value of local_GP->put */
+
+		dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
+			"channel=%d\n", put, ch->partid, ch->number);
+
+		send_IPI = 1;
+
+		/*
+		 * We need to ensure that the message referenced by
+		 * local_GP->put is not XPC_M_READY or that local_GP->put
+		 * equals w_local_GP.put, so we'll go have a look.
+		 */
+		initial_put = put;
+	}
+
+	if (send_IPI) {
+		xpc_IPI_send_msgrequest(ch);
+	}
+}
+
+
+/*
+ * Common code that does the actual sending of the message by advancing the
+ * local message queue's Put value and sends an IPI to the partition the
+ * message is being sent to.
+ */
+static enum xpc_retval
+xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
+			xpc_notify_func func, void *key)
+{
+	enum xpc_retval ret = xpcSuccess;
+	struct xpc_notify *notify = NULL;   // >>> to keep the compiler happy!!
+	s64 put, msg_number = msg->number;
+
+
+	DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
+	DBUG_ON((((u64) msg - (u64) ch->local_msgqueue) / ch->msg_size) !=
+					msg_number % ch->local_nentries);
+	DBUG_ON(msg->flags & XPC_M_READY);
+
+	if (ch->flags & XPC_C_DISCONNECTING) {
+		/* drop the reference grabbed in xpc_allocate_msg() */
+		xpc_msgqueue_deref(ch);
+		return ch->reason;
+	}
+
+	if (notify_type != 0) {
+		/*
+		 * Tell the remote side to send an ACK interrupt when the
+		 * message has been delivered.
+		 */
+		msg->flags |= XPC_M_INTERRUPT;
+
+		atomic_inc(&ch->n_to_notify);
+
+		notify = &ch->notify_queue[msg_number % ch->local_nentries];
+		notify->func = func;
+		notify->key = key;
+		(volatile u8) notify->type = notify_type;
+
+		// >>> is a mb() needed here?
+
+		if (ch->flags & XPC_C_DISCONNECTING) {
+			/*
+			 * An error occurred between our last error check and
+			 * this one. We will try to clear the type field from
+			 * the notify entry. If we succeed then
+			 * xpc_disconnect_channel() didn't already process
+			 * the notify entry.
+			 */
+			if (cmpxchg(&notify->type, notify_type, 0) ==
+								notify_type) {
+				atomic_dec(&ch->n_to_notify);
+				ret = ch->reason;
+			}
+
+			/* drop the reference grabbed in xpc_allocate_msg() */
+			xpc_msgqueue_deref(ch);
+			return ret;
+		}
+	}
+
+	msg->flags |= XPC_M_READY;
+
+	/*
+	 * The preceding store of msg->flags must occur before the following
+	 * load of ch->local_GP->put.
+	 */
+	mb();
+
+	/* see if the message is next in line to be sent, if so send it */
+
+	put = ch->local_GP->put;
+	if (put == msg_number) {
+		xpc_send_msgs(ch, put);
+	}
+
+	/* drop the reference grabbed in xpc_allocate_msg() */
+	xpc_msgqueue_deref(ch);
+	return ret;
+}
+
+
+/*
+ * Send a message previously allocated using xpc_initiate_allocate() on the
+ * specified channel connected to the specified partition.
+ *
+ * This routine will not wait for the message to be received, nor will
+ * notification be given when it does happen. Once this routine has returned
+ * the message entry allocated via xpc_initiate_allocate() is no longer
+ * accessable to the caller.
+ *
+ * This routine, although called by users, does not call xpc_part_ref() to
+ * ensure that the partition infrastructure is in place. It relies on the
+ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+ *
+ * Arguments:
+ *
+ *	partid - ID of partition to which the channel is connected.
+ *	ch_number - channel # to send message on.
+ *	payload - pointer to the payload area allocated via
+ *			xpc_initiate_allocate().
+ */
+enum xpc_retval
+xpc_initiate_send(partid_t partid, int ch_number, void *payload)
+{
+	struct xpc_partition *part = &xpc_partitions[partid];
+	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+	enum xpc_retval ret;
+
+
+	dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+		partid, ch_number);
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+	DBUG_ON(msg == NULL);
+
+	ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);
+
+	return ret;
+}
+
+
+/*
+ * Send a message previously allocated using xpc_initiate_allocate on the
+ * specified channel connected to the specified partition.
+ *
+ * This routine will not wait for the message to be sent. Once this routine
+ * has returned the message entry allocated via xpc_initiate_allocate() is no
+ * longer accessable to the caller.
+ *
+ * Once the remote end of the channel has received the message, the function
+ * passed as an argument to xpc_initiate_send_notify() will be called. This
+ * allows the sender to free up or re-use any buffers referenced by the
+ * message, but does NOT mean the message has been processed at the remote
+ * end by a receiver.
+ *
+ * If this routine returns an error, the caller's function will NOT be called.
+ *
+ * This routine, although called by users, does not call xpc_part_ref() to
+ * ensure that the partition infrastructure is in place. It relies on the
+ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+ *
+ * Arguments:
+ *
+ *	partid - ID of partition to which the channel is connected.
+ *	ch_number - channel # to send message on.
+ *	payload - pointer to the payload area allocated via
+ *			xpc_initiate_allocate().
+ *	func - function to call with asynchronous notification of message
+ *		  receipt. THIS FUNCTION MUST BE NON-BLOCKING.
+ *	key - user-defined key to be passed to the function when it's called.
+ */
+enum xpc_retval
+xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,
+				xpc_notify_func func, void *key)
+{
+	struct xpc_partition *part = &xpc_partitions[partid];
+	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+	enum xpc_retval ret;
+
+
+	dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+		partid, ch_number);
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+	DBUG_ON(msg == NULL);
+	DBUG_ON(func == NULL);
+
+	ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,
+								func, key);
+	return ret;
+}
+
+
+static struct xpc_msg *
+xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
+{
+	struct xpc_partition *part = &xpc_partitions[ch->partid];
+	struct xpc_msg *remote_msg, *msg;
+	u32 msg_index, nmsgs;
+	u64 msg_offset;
+	enum xpc_retval ret;
+
+
+	if (down_interruptible(&ch->msg_to_pull_sema) != 0) {
+		/* we were interrupted by a signal */
+		return NULL;
+	}
+
+	while (get >= ch->next_msg_to_pull) {
+
+		/* pull as many messages as are ready and able to be pulled */
+
+		msg_index = ch->next_msg_to_pull % ch->remote_nentries;
+
+		DBUG_ON(ch->next_msg_to_pull >=
+					(volatile s64) ch->w_remote_GP.put);
+		nmsgs =  (volatile s64) ch->w_remote_GP.put -
+						ch->next_msg_to_pull;
+		if (msg_index + nmsgs > ch->remote_nentries) {
+			/* ignore the ones that wrap the msg queue for now */
+			nmsgs = ch->remote_nentries - msg_index;
+		}
+
+		msg_offset = msg_index * ch->msg_size;
+		msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+								msg_offset);
+		remote_msg = (struct xpc_msg *) (ch->remote_msgqueue_pa +
+								msg_offset);
+
+		if ((ret = xpc_pull_remote_cachelines(part, msg, remote_msg,
+				nmsgs * ch->msg_size)) != xpcSuccess) {
+
+			dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
+				" msg %ld from partition %d, channel=%d, "
+				"ret=%d\n", nmsgs, ch->next_msg_to_pull,
+				ch->partid, ch->number, ret);
+
+			XPC_DEACTIVATE_PARTITION(part, ret);
+
+			up(&ch->msg_to_pull_sema);
+			return NULL;
+		}
+
+		mb();	/* >>> this may not be needed, we're not sure */
+
+		ch->next_msg_to_pull += nmsgs;
+	}
+
+	up(&ch->msg_to_pull_sema);
+
+	/* return the message we were looking for */
+	msg_offset = (get % ch->remote_nentries) * ch->msg_size;
+	msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue + msg_offset);
+
+	return msg;
+}
+
+
+/*
+ * Get a message to be delivered.
+ */
+static struct xpc_msg *
+xpc_get_deliverable_msg(struct xpc_channel *ch)
+{
+	struct xpc_msg *msg = NULL;
+	s64 get;
+
+
+	do {
+		if ((volatile u32) ch->flags & XPC_C_DISCONNECTING) {
+			break;
+		}
+
+		get = (volatile s64) ch->w_local_GP.get;
+		if (get == (volatile s64) ch->w_remote_GP.put) {
+			break;
+		}
+
+		/* There are messages waiting to be pulled and delivered.
+		 * We need to try to secure one for ourselves. We'll do this
+		 * by trying to increment w_local_GP.get and hope that no one
+		 * else beats us to it. If they do, we'll we'll simply have
+		 * to try again for the next one.
+	 	 */
+
+		if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
+			/* we got the entry referenced by get */
+
+			dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
+				"partid=%d, channel=%d\n", get + 1,
+				ch->partid, ch->number);
+
+			/* pull the message from the remote partition */
+
+			msg = xpc_pull_remote_msg(ch, get);
+
+			DBUG_ON(msg != NULL && msg->number != get);
+			DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
+			DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
+
+			break;
+		}
+
+	} while (1);
+
+	return msg;
+}
+
+
+/*
+ * Deliver a message to its intended recipient.
+ */
+void
+xpc_deliver_msg(struct xpc_channel *ch)
+{
+	struct xpc_msg *msg;
+
+
+	if ((msg = xpc_get_deliverable_msg(ch)) != NULL) {
+
+		/*
+		 * This ref is taken to protect the payload itself from being
+		 * freed before the user is finished with it, which the user
+		 * indicates by calling xpc_initiate_received().
+		 */
+		xpc_msgqueue_ref(ch);
+
+		atomic_inc(&ch->kthreads_active);
+
+		if (ch->func != NULL) {
+			dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "
+				"msg_number=%ld, partid=%d, channel=%d\n",
+				(void *) msg, msg->number, ch->partid,
+				ch->number);
+
+			/* deliver the message to its intended recipient */
+			ch->func(xpcMsgReceived, ch->partid, ch->number,
+					&msg->payload, ch->key);
+
+			dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "
+				"msg_number=%ld, partid=%d, channel=%d\n",
+				(void *) msg, msg->number, ch->partid,
+				ch->number);
+		}
+
+		atomic_dec(&ch->kthreads_active);
+	}
+}
+
+
+/*
+ * Now we actually acknowledge the messages that have been delivered and ack'd
+ * by advancing the cached remote message queue's Get value and if requested
+ * send an IPI to the message sender's partition.
+ */
+static void
+xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
+{
+	struct xpc_msg *msg;
+	s64 get = initial_get + 1;
+	int send_IPI = 0;
+
+
+	while (1) {
+
+		while (1) {
+			if (get == (volatile s64) ch->w_local_GP.get) {
+				break;
+			}
+
+			msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+			       (get % ch->remote_nentries) * ch->msg_size);
+
+			if (!(msg->flags & XPC_M_DONE)) {
+				break;
+			}
+
+			msg_flags |= msg->flags;
+			get++;
+		}
+
+		if (get == initial_get) {
+			/* nothing's changed */
+			break;
+		}
+
+		if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
+								initial_get) {
+			/* someone else beat us to it */
+			DBUG_ON((volatile s64) ch->local_GP->get <=
+								initial_get);
+			break;
+		}
+
+		/* we just set the new value of local_GP->get */
+
+		dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
+			"channel=%d\n", get, ch->partid, ch->number);
+
+		send_IPI = (msg_flags & XPC_M_INTERRUPT);
+
+		/*
+		 * We need to ensure that the message referenced by
+		 * local_GP->get is not XPC_M_DONE or that local_GP->get
+		 * equals w_local_GP.get, so we'll go have a look.
+		 */
+		initial_get = get;
+	}
+
+	if (send_IPI) {
+		xpc_IPI_send_msgrequest(ch);
+	}
+}
+
+
+/*
+ * Acknowledge receipt of a delivered message.
+ *
+ * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
+ * that sent the message.
+ *
+ * This function, although called by users, does not call xpc_part_ref() to
+ * ensure that the partition infrastructure is in place. It relies on the
+ * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().
+ *
+ * Arguments:
+ *
+ *	partid - ID of partition to which the channel is connected.
+ *	ch_number - channel # message received on.
+ *	payload - pointer to the payload area allocated via
+ *			xpc_initiate_allocate().
+ */
+void
+xpc_initiate_received(partid_t partid, int ch_number, void *payload)
+{
+	struct xpc_partition *part = &xpc_partitions[partid];
+	struct xpc_channel *ch;
+	struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+	s64 get, msg_number = msg->number;
+
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+	DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+
+	ch = &part->channels[ch_number];
+
+	dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
+		(void *) msg, msg_number, ch->partid, ch->number);
+
+	DBUG_ON((((u64) msg - (u64) ch->remote_msgqueue) / ch->msg_size) !=
+					msg_number % ch->remote_nentries);
+	DBUG_ON(msg->flags & XPC_M_DONE);
+
+	msg->flags |= XPC_M_DONE;
+
+	/*
+	 * The preceding store of msg->flags must occur before the following
+	 * load of ch->local_GP->get.
+	 */
+	mb();
+
+	/*
+	 * See if this message is next in line to be acknowledged as having
+	 * been delivered.
+	 */
+	get = ch->local_GP->get;
+	if (get == msg_number) {
+		xpc_acknowledge_msgs(ch, get, msg->flags);
+	}
+
+	/* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg()  */
+	xpc_msgqueue_deref(ch);
+}
+
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
new file mode 100644
index 0000000..177ddb7
--- /dev/null
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -0,0 +1,1064 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) support - standard version.
+ *
+ *	XPC provides a message passing capability that crosses partition
+ *	boundaries. This module is made up of two parts:
+ *
+ *	    partition	This part detects the presence/absence of other
+ *			partitions. It provides a heartbeat and monitors
+ *			the heartbeats of other partitions.
+ *
+ *	    channel	This part manages the channels and sends/receives
+ *			messages across them to/from other partitions.
+ *
+ *	There are a couple of additional functions residing in XP, which
+ *	provide an interface to XPC for its users.
+ *
+ *
+ *	Caveats:
+ *
+ *	  . We currently have no way to determine which nasid an IPI came
+ *	    from. Thus, xpc_IPI_send() does a remote AMO write followed by
+ *	    an IPI. The AMO indicates where data is to be pulled from, so
+ *	    after the IPI arrives, the remote partition checks the AMO word.
+ *	    The IPI can actually arrive before the AMO however, so other code
+ *	    must periodically check for this case. Also, remote AMO operations
+ *	    do not reliably time out. Thus we do a remote PIO read solely to
+ *	    know whether the remote partition is down and whether we should
+ *	    stop sending IPIs to it. This remote PIO read operation is set up
+ *	    in a special nofault region so SAL knows to ignore (and cleanup)
+ *	    any errors due to the remote AMO write, PIO read, and/or PIO
+ *	    write operations.
+ *
+ *	    If/when new hardware solves this IPI problem, we should abandon
+ *	    the current approach.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/cache.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/uaccess.h>
+#include "xpc.h"
+
+
+/* define two XPC debug device structures to be used with dev_dbg() et al */
+
+struct device_driver xpc_dbg_name = {
+	.name = "xpc"
+};
+
+struct device xpc_part_dbg_subname = {
+	.bus_id = {0},		/* set to "part" at xpc_init() time */
+	.driver = &xpc_dbg_name
+};
+
+struct device xpc_chan_dbg_subname = {
+	.bus_id = {0},		/* set to "chan" at xpc_init() time */
+	.driver = &xpc_dbg_name
+};
+
+struct device *xpc_part = &xpc_part_dbg_subname;
+struct device *xpc_chan = &xpc_chan_dbg_subname;
+
+
+/* systune related variables for /proc/sys directories */
+
+static int xpc_hb_min = 1;
+static int xpc_hb_max = 10;
+
+static int xpc_hb_check_min = 10;
+static int xpc_hb_check_max = 120;
+
+static ctl_table xpc_sys_xpc_hb_dir[] = {
+	{
+		1,
+		"hb_interval",
+		&xpc_hb_interval,
+		sizeof(int),
+		0644,
+		NULL,
+		&proc_dointvec_minmax,
+		&sysctl_intvec,
+		NULL,
+		&xpc_hb_min, &xpc_hb_max
+	},
+	{
+		2,
+		"hb_check_interval",
+		&xpc_hb_check_interval,
+		sizeof(int),
+		0644,
+		NULL,
+		&proc_dointvec_minmax,
+		&sysctl_intvec,
+		NULL,
+		&xpc_hb_check_min, &xpc_hb_check_max
+	},
+	{0}
+};
+static ctl_table xpc_sys_xpc_dir[] = {
+	{
+		1,
+		"hb",
+		NULL,
+		0,
+		0555,
+		xpc_sys_xpc_hb_dir
+	},
+	{0}
+};
+static ctl_table xpc_sys_dir[] = {
+	{
+		1,
+		"xpc",
+		NULL,
+		0,
+		0555,
+		xpc_sys_xpc_dir
+	},
+	{0}
+};
+static struct ctl_table_header *xpc_sysctl;
+
+
+/* #of IRQs received */
+static atomic_t xpc_act_IRQ_rcvd;
+
+/* IRQ handler notifies this wait queue on receipt of an IRQ */
+static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
+
+static unsigned long xpc_hb_check_timeout;
+
+/* xpc_hb_checker thread exited notification */
+static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
+
+/* xpc_discovery thread exited notification */
+static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
+
+
+static struct timer_list xpc_hb_timer;
+
+
+static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
+
+
+/*
+ * Notify the heartbeat check thread that an IRQ has been received.
+ */
+static irqreturn_t
+xpc_act_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	atomic_inc(&xpc_act_IRQ_rcvd);
+	wake_up_interruptible(&xpc_act_IRQ_wq);
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * Timer to produce the heartbeat.  The timer structures function is
+ * already set when this is initially called.  A tunable is used to
+ * specify when the next timeout should occur.
+ */
+static void
+xpc_hb_beater(unsigned long dummy)
+{
+	xpc_vars->heartbeat++;
+
+	if (jiffies >= xpc_hb_check_timeout) {
+		wake_up_interruptible(&xpc_act_IRQ_wq);
+	}
+
+	xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
+	add_timer(&xpc_hb_timer);
+}
+
+
+/*
+ * This thread is responsible for nearly all of the partition
+ * activation/deactivation.
+ */
+static int
+xpc_hb_checker(void *ignore)
+{
+	int last_IRQ_count = 0;
+	int new_IRQ_count;
+	int force_IRQ=0;
+
+
+	/* this thread was marked active by xpc_hb_init() */
+
+	daemonize(XPC_HB_CHECK_THREAD_NAME);
+
+	set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+
+	xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
+
+	while (!(volatile int) xpc_exiting) {
+
+		/* wait for IRQ or timeout */
+		(void) wait_event_interruptible(xpc_act_IRQ_wq,
+			    (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
+					jiffies >= xpc_hb_check_timeout ||
+						(volatile int) xpc_exiting));
+
+		dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
+			"been received\n",
+			(int) (xpc_hb_check_timeout - jiffies),
+			atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);
+
+
+		/* checking of remote heartbeats is skewed by IRQ handling */
+		if (jiffies >= xpc_hb_check_timeout) {
+			dev_dbg(xpc_part, "checking remote heartbeats\n");
+			xpc_check_remote_hb();
+
+			/*
+			 * We need to periodically recheck to ensure no
+			 * IPI/AMO pairs have been missed.  That check
+			 * must always reset xpc_hb_check_timeout.
+			 */
+			force_IRQ = 1;
+		}
+
+
+		new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
+		if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
+			force_IRQ = 0;
+
+			dev_dbg(xpc_part, "found an IRQ to process; will be "
+				"resetting xpc_hb_check_timeout\n");
+
+			last_IRQ_count += xpc_identify_act_IRQ_sender();
+			if (last_IRQ_count < new_IRQ_count) {
+				/* retry once to help avoid missing AMO */
+				(void) xpc_identify_act_IRQ_sender();
+			}
+			last_IRQ_count = new_IRQ_count;
+
+			xpc_hb_check_timeout = jiffies +
+					   (xpc_hb_check_interval * HZ);
+		}
+	}
+
+	dev_dbg(xpc_part, "heartbeat checker is exiting\n");
+
+
+	/* mark this thread as inactive */
+	up(&xpc_hb_checker_exited);
+	return 0;
+}
+
+
+/*
+ * This thread will attempt to discover other partitions to activate
+ * based on info provided by SAL. This new thread is short lived and
+ * will exit once discovery is complete.
+ */
+static int
+xpc_initiate_discovery(void *ignore)
+{
+	daemonize(XPC_DISCOVERY_THREAD_NAME);
+
+	xpc_discovery();
+
+	dev_dbg(xpc_part, "discovery thread is exiting\n");
+
+	/* mark this thread as inactive */
+	up(&xpc_discovery_exited);
+	return 0;
+}
+
+
+/*
+ * Establish first contact with the remote partititon. This involves pulling
+ * the XPC per partition variables from the remote partition and waiting for
+ * the remote partition to pull ours.
+ */
+static enum xpc_retval
+xpc_make_first_contact(struct xpc_partition *part)
+{
+	enum xpc_retval ret;
+
+
+	while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {
+		if (ret != xpcRetry) {
+			XPC_DEACTIVATE_PARTITION(part, ret);
+			return ret;
+		}
+
+		dev_dbg(xpc_chan, "waiting to make first contact with "
+			"partition %d\n", XPC_PARTID(part));
+
+		/* wait a 1/4 of a second or so */
+		set_current_state(TASK_INTERRUPTIBLE);
+		(void) schedule_timeout(0.25 * HZ);
+
+		if (part->act_state == XPC_P_DEACTIVATING) {
+			return part->reason;
+		}
+	}
+
+	return xpc_mark_partition_active(part);
+}
+
+
+/*
+ * The first kthread assigned to a newly activated partition is the one
+ * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to
+ * that kthread until the partition is brought down, at which time that kthread
+ * returns back to XPC HB. (The return of that kthread will signify to XPC HB
+ * that XPC has dismantled all communication infrastructure for the associated
+ * partition.) This kthread becomes the channel manager for that partition.
+ *
+ * Each active partition has a channel manager, who, besides connecting and
+ * disconnecting channels, will ensure that each of the partition's connected
+ * channels has the required number of assigned kthreads to get the work done.
+ */
+static void
+xpc_channel_mgr(struct xpc_partition *part)
+{
+	while (part->act_state != XPC_P_DEACTIVATING ||
+				atomic_read(&part->nchannels_active) > 0) {
+
+		xpc_process_channel_activity(part);
+
+
+		/*
+		 * Wait until we've been requested to activate kthreads or
+		 * all of the channel's message queues have been torn down or
+		 * a signal is pending.
+		 *
+		 * The channel_mgr_requests is set to 1 after being awakened,
+		 * This is done to prevent the channel mgr from making one pass
+		 * through the loop for each request, since he will
+		 * be servicing all the requests in one pass. The reason it's
+		 * set to 1 instead of 0 is so that other kthreads will know
+		 * that the channel mgr is running and won't bother trying to
+		 * wake him up.
+		 */
+		atomic_dec(&part->channel_mgr_requests);
+		(void) wait_event_interruptible(part->channel_mgr_wq,
+				(atomic_read(&part->channel_mgr_requests) > 0 ||
+				(volatile u64) part->local_IPI_amo != 0 ||
+				((volatile u8) part->act_state ==
+							XPC_P_DEACTIVATING &&
+				atomic_read(&part->nchannels_active) == 0)));
+		atomic_set(&part->channel_mgr_requests, 1);
+
+		// >>> Does it need to wakeup periodically as well? In case we
+		// >>> miscalculated the #of kthreads to wakeup or create?
+	}
+}
+
+
+/*
+ * When XPC HB determines that a partition has come up, it will create a new
+ * kthread and that kthread will call this function to attempt to set up the
+ * basic infrastructure used for Cross Partition Communication with the newly
+ * upped partition.
+ *
+ * The kthread that was created by XPC HB and which setup the XPC
+ * infrastructure will remain assigned to the partition until the partition
+ * goes down. At which time the kthread will teardown the XPC infrastructure
+ * and then exit.
+ *
+ * XPC HB will put the remote partition's XPC per partition specific variables
+ * physical address into xpc_partitions[partid].remote_vars_part_pa prior to
+ * calling xpc_partition_up().
+ */
+static void
+xpc_partition_up(struct xpc_partition *part)
+{
+	DBUG_ON(part->channels != NULL);
+
+	dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));
+
+	if (xpc_setup_infrastructure(part) != xpcSuccess) {
+		return;
+	}
+
+	/*
+	 * The kthread that XPC HB called us with will become the
+	 * channel manager for this partition. It will not return
+	 * back to XPC HB until the partition's XPC infrastructure
+	 * has been dismantled.
+	 */
+
+	(void) xpc_part_ref(part);	/* this will always succeed */
+
+	if (xpc_make_first_contact(part) == xpcSuccess) {
+		xpc_channel_mgr(part);
+	}
+
+	xpc_part_deref(part);
+
+	xpc_teardown_infrastructure(part);
+}
+
+
+static int
+xpc_activating(void *__partid)
+{
+	partid_t partid = (u64) __partid;
+	struct xpc_partition *part = &xpc_partitions[partid];
+	unsigned long irq_flags;
+	struct sched_param param = { sched_priority: MAX_USER_RT_PRIO - 1 };
+	int ret;
+
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+
+	spin_lock_irqsave(&part->act_lock, irq_flags);
+
+	if (part->act_state == XPC_P_DEACTIVATING) {
+		part->act_state = XPC_P_INACTIVE;
+		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+		part->remote_rp_pa = 0;
+		return 0;
+	}
+
+	/* indicate the thread is activating */
+	DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);
+	part->act_state = XPC_P_ACTIVATING;
+
+	XPC_SET_REASON(part, 0, 0);
+	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+	dev_dbg(xpc_part, "bringing partition %d up\n", partid);
+
+	daemonize("xpc%02d", partid);
+
+	/*
+	 * This thread needs to run at a realtime priority to prevent a
+	 * significant performance degradation.
+	 */
+	ret = sched_setscheduler(current, SCHED_FIFO, &param);
+	if (ret != 0) {
+		dev_warn(xpc_part, "unable to set pid %d to a realtime "
+			"priority, ret=%d\n", current->pid, ret);
+	}
+
+	/* allow this thread and its children to run on any CPU */
+	set_cpus_allowed(current, CPU_MASK_ALL);
+
+	/*
+	 * Register the remote partition's AMOs with SAL so it can handle
+	 * and cleanup errors within that address range should the remote
+	 * partition go down. We don't unregister this range because it is
+	 * difficult to tell when outstanding writes to the remote partition
+	 * are finished and thus when it is safe to unregister. This should
+	 * not result in wasted space in the SAL xp_addr_region table because
+	 * we should get the same page for remote_amos_page_pa after module
+	 * reloads and system reboots.
+	 */
+	if (sn_register_xp_addr_region(part->remote_amos_page_pa,
+							PAGE_SIZE, 1) < 0) {
+		dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
+			"xp_addr region\n", partid);
+
+		spin_lock_irqsave(&part->act_lock, irq_flags);
+		part->act_state = XPC_P_INACTIVE;
+		XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);
+		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+		part->remote_rp_pa = 0;
+		return 0;
+	}
+
+	XPC_ALLOW_HB(partid, xpc_vars);
+	xpc_IPI_send_activated(part);
+
+
+	/*
+	 * xpc_partition_up() holds this thread and marks this partition as
+	 * XPC_P_ACTIVE by calling xpc_hb_mark_active().
+	 */
+	(void) xpc_partition_up(part);
+
+	xpc_mark_partition_inactive(part);
+
+	if (part->reason == xpcReactivating) {
+		/* interrupting ourselves results in activating partition */
+		xpc_IPI_send_reactivate(part);
+	}
+
+	return 0;
+}
+
+
+void
+xpc_activate_partition(struct xpc_partition *part)
+{
+	partid_t partid = XPC_PARTID(part);
+	unsigned long irq_flags;
+	pid_t pid;
+
+
+	spin_lock_irqsave(&part->act_lock, irq_flags);
+
+	pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
+
+	DBUG_ON(part->act_state != XPC_P_INACTIVE);
+
+	if (pid > 0) {
+		part->act_state = XPC_P_ACTIVATION_REQ;
+		XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
+	} else {
+		XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
+	}
+
+	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+}
+
+
+/*
+ * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
+ * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
+ * than one partition, we use an AMO_t structure per partition to indicate
+ * whether a partition has sent an IPI or not.  >>> If it has, then wake up the
+ * associated kthread to handle it.
+ *
+ * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
+ * running on other partitions.
+ *
+ * Noteworthy Arguments:
+ *
+ *	irq - Interrupt ReQuest number. NOT USED.
+ *
+ *	dev_id - partid of IPI's potential sender.
+ *
+ *	regs - processor's context before the processor entered
+ *	       interrupt code. NOT USED.
+ */
+irqreturn_t
+xpc_notify_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	partid_t partid = (partid_t) (u64) dev_id;
+	struct xpc_partition *part = &xpc_partitions[partid];
+
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+
+	if (xpc_part_ref(part)) {
+		xpc_check_for_channel_activity(part);
+
+		xpc_part_deref(part);
+	}
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor
+ * because the write to their associated IPI amo completed after the IRQ/IPI
+ * was received.
+ */
+void
+xpc_dropped_IPI_check(struct xpc_partition *part)
+{
+	if (xpc_part_ref(part)) {
+		xpc_check_for_channel_activity(part);
+
+		part->dropped_IPI_timer.expires = jiffies +
+							XPC_P_DROPPED_IPI_WAIT;
+		add_timer(&part->dropped_IPI_timer);
+		xpc_part_deref(part);
+	}
+}
+
+
+void
+xpc_activate_kthreads(struct xpc_channel *ch, int needed)
+{
+	int idle = atomic_read(&ch->kthreads_idle);
+	int assigned = atomic_read(&ch->kthreads_assigned);
+	int wakeup;
+
+
+	DBUG_ON(needed <= 0);
+
+	if (idle > 0) {
+		wakeup = (needed > idle) ? idle : needed;
+		needed -= wakeup;
+
+		dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
+			"channel=%d\n", wakeup, ch->partid, ch->number);
+
+		/* only wakeup the requested number of kthreads */
+		wake_up_nr(&ch->idle_wq, wakeup);
+	}
+
+	if (needed <= 0) {
+		return;
+	}
+
+	if (needed + assigned > ch->kthreads_assigned_limit) {
+		needed = ch->kthreads_assigned_limit - assigned;
+		// >>>should never be less than 0
+		if (needed <= 0) {
+			return;
+		}
+	}
+
+	dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
+		needed, ch->partid, ch->number);
+
+	xpc_create_kthreads(ch, needed);
+}
+
+
+/*
+ * This function is where XPC's kthreads wait for messages to deliver.
+ */
+static void
+xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
+{
+	do {
+		/* deliver messages to their intended recipients */
+
+		while ((volatile s64) ch->w_local_GP.get <
+				(volatile s64) ch->w_remote_GP.put &&
+					!((volatile u32) ch->flags &
+						XPC_C_DISCONNECTING)) {
+			xpc_deliver_msg(ch);
+		}
+
+		if (atomic_inc_return(&ch->kthreads_idle) >
+						ch->kthreads_idle_limit) {
+			/* too many idle kthreads on this channel */
+			atomic_dec(&ch->kthreads_idle);
+			break;
+		}
+
+		dev_dbg(xpc_chan, "idle kthread calling "
+			"wait_event_interruptible_exclusive()\n");
+
+		(void) wait_event_interruptible_exclusive(ch->idle_wq,
+				((volatile s64) ch->w_local_GP.get <
+					(volatile s64) ch->w_remote_GP.put ||
+				((volatile u32) ch->flags &
+						XPC_C_DISCONNECTING)));
+
+		atomic_dec(&ch->kthreads_idle);
+
+	} while (!((volatile u32) ch->flags & XPC_C_DISCONNECTING));
+}
+
+
+static int
+xpc_daemonize_kthread(void *args)
+{
+	partid_t partid = XPC_UNPACK_ARG1(args);
+	u16 ch_number = XPC_UNPACK_ARG2(args);
+	struct xpc_partition *part = &xpc_partitions[partid];
+	struct xpc_channel *ch;
+	int n_needed;
+
+
+	daemonize("xpc%02dc%d", partid, ch_number);
+
+	dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
+		partid, ch_number);
+
+	ch = &part->channels[ch_number];
+
+	if (!(ch->flags & XPC_C_DISCONNECTING)) {
+		DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
+
+		/* let registerer know that connection has been established */
+
+		if (atomic_read(&ch->kthreads_assigned) == 1) {
+			xpc_connected_callout(ch);
+
+			/*
+			 * It is possible that while the callout was being
+			 * made that the remote partition sent some messages.
+			 * If that is the case, we may need to activate
+			 * additional kthreads to help deliver them. We only
+			 * need one less than total #of messages to deliver.
+			 */
+			n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;
+			if (n_needed > 0 &&
+					!(ch->flags & XPC_C_DISCONNECTING)) {
+				xpc_activate_kthreads(ch, n_needed);
+			}
+		}
+
+		xpc_kthread_waitmsgs(part, ch);
+	}
+
+	if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
+			((ch->flags & XPC_C_CONNECTCALLOUT) ||
+				(ch->reason != xpcUnregistering &&
+					ch->reason != xpcOtherUnregistering))) {
+		xpc_disconnected_callout(ch);
+	}
+
+
+	xpc_msgqueue_deref(ch);
+
+	dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
+		partid, ch_number);
+
+	xpc_part_deref(part);
+	return 0;
+}
+
+
+/*
+ * For each partition that XPC has established communications with, there is
+ * a minimum of one kernel thread assigned to perform any operation that
+ * may potentially sleep or block (basically the callouts to the asynchronous
+ * functions registered via xpc_connect()).
+ *
+ * Additional kthreads are created and destroyed by XPC as the workload
+ * demands.
+ *
+ * A kthread is assigned to one of the active channels that exists for a given
+ * partition.
+ */
+void
+xpc_create_kthreads(struct xpc_channel *ch, int needed)
+{
+	unsigned long irq_flags;
+	pid_t pid;
+	u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
+
+
+	while (needed-- > 0) {
+		pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
+		if (pid < 0) {
+			/* the fork failed */
+
+			if (atomic_read(&ch->kthreads_assigned) <
+						ch->kthreads_idle_limit) {
+				/*
+				 * Flag this as an error only if we have an
+				 * insufficient #of kthreads for the channel
+				 * to function.
+				 *
+				 * No xpc_msgqueue_ref() is needed here since
+				 * the channel mgr is doing this.
+				 */
+				spin_lock_irqsave(&ch->lock, irq_flags);
+				XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
+								&irq_flags);
+				spin_unlock_irqrestore(&ch->lock, irq_flags);
+			}
+			break;
+		}
+
+		/*
+		 * The following is done on behalf of the newly created
+		 * kthread. That kthread is responsible for doing the
+		 * counterpart to the following before it exits.
+		 */
+		(void) xpc_part_ref(&xpc_partitions[ch->partid]);
+		xpc_msgqueue_ref(ch);
+		atomic_inc(&ch->kthreads_assigned);
+		ch->kthreads_created++;	// >>> temporary debug only!!!
+	}
+}
+
+
+void
+xpc_disconnect_wait(int ch_number)
+{
+	partid_t partid;
+	struct xpc_partition *part;
+	struct xpc_channel *ch;
+
+
+	/* now wait for all callouts to the caller's function to cease */
+	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+		part = &xpc_partitions[partid];
+
+		if (xpc_part_ref(part)) {
+			ch = &part->channels[ch_number];
+
+// >>> how do we keep from falling into the window between our check and going
+// >>> down and coming back up where sema is re-inited?
+			if (ch->flags & XPC_C_SETUP) {
+				(void) down(&ch->teardown_sema);
+			}
+
+			xpc_part_deref(part);
+		}
+	}
+}
+
+
+static void
+xpc_do_exit(void)
+{
+	partid_t partid;
+	int active_part_count;
+	struct xpc_partition *part;
+
+
+	/* now it's time to eliminate our heartbeat */
+	del_timer_sync(&xpc_hb_timer);
+	xpc_vars->heartbeating_to_mask = 0;
+
+	/* indicate to others that our reserved page is uninitialized */
+	xpc_rsvd_page->vars_pa = 0;
+
+	/*
+	 * Ignore all incoming interrupts. Without interupts the heartbeat
+	 * checker won't activate any new partitions that may come up.
+	 */
+	free_irq(SGI_XPC_ACTIVATE, NULL);
+
+	/*
+	 * Cause the heartbeat checker and the discovery threads to exit.
+	 * We don't want them attempting to activate new partitions as we
+	 * try to deactivate the existing ones.
+	 */
+	xpc_exiting = 1;
+	wake_up_interruptible(&xpc_act_IRQ_wq);
+
+	/* wait for the heartbeat checker thread to mark itself inactive */
+	down(&xpc_hb_checker_exited);
+
+	/* wait for the discovery thread to mark itself inactive */
+	down(&xpc_discovery_exited);
+
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(0.3 * HZ);
+	set_current_state(TASK_RUNNING);
+
+
+	/* wait for all partitions to become inactive */
+
+	do {
+		active_part_count = 0;
+
+		for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+			part = &xpc_partitions[partid];
+			if (part->act_state != XPC_P_INACTIVE) {
+				active_part_count++;
+
+				XPC_DEACTIVATE_PARTITION(part, xpcUnloading);
+			}
+		}
+
+		if (active_part_count) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(0.3 * HZ);
+			set_current_state(TASK_RUNNING);
+		}
+
+	} while (active_part_count > 0);
+
+
+	/* close down protections for IPI operations */
+	xpc_restrict_IPI_ops();
+
+
+	/* clear the interface to XPC's functions */
+	xpc_clear_interface();
+
+	if (xpc_sysctl) {
+		unregister_sysctl_table(xpc_sysctl);
+	}
+}
+
+
+int __init
+xpc_init(void)
+{
+	int ret;
+	partid_t partid;
+	struct xpc_partition *part;
+	pid_t pid;
+
+
+	/*
+	 * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
+	 * both a partition's reserved page and its XPC variables. Its size was
+	 * based on the size of a reserved page. So we need to ensure that the
+	 * XPC variables will fit as well.
+	 */
+	if (XPC_VARS_ALIGNED_SIZE > XPC_RSVD_PAGE_ALIGNED_SIZE) {
+		dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
+		return -EPERM;
+	}
+	DBUG_ON((u64) xpc_remote_copy_buffer !=
+				L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));
+
+	snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
+	snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
+
+	xpc_sysctl = register_sysctl_table(xpc_sys_dir, 1);
+
+	/*
+	 * The first few fields of each entry of xpc_partitions[] need to
+	 * be initialized now so that calls to xpc_connect() and
+	 * xpc_disconnect() can be made prior to the activation of any remote
+	 * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
+	 * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
+	 * PARTITION HAS BEEN ACTIVATED.
+	 */
+	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+		part = &xpc_partitions[partid];
+
+		DBUG_ON((u64) part != L1_CACHE_ALIGN((u64) part));
+
+		part->act_IRQ_rcvd = 0;
+		spin_lock_init(&part->act_lock);
+		part->act_state = XPC_P_INACTIVE;
+		XPC_SET_REASON(part, 0, 0);
+		part->setup_state = XPC_P_UNSET;
+		init_waitqueue_head(&part->teardown_wq);
+		atomic_set(&part->references, 0);
+	}
+
+	/*
+	 * Open up protections for IPI operations (and AMO operations on
+	 * Shub 1.1 systems).
+	 */
+	xpc_allow_IPI_ops();
+
+	/*
+	 * Interrupts being processed will increment this atomic variable and
+	 * awaken the heartbeat thread which will process the interrupts.
+	 */
+	atomic_set(&xpc_act_IRQ_rcvd, 0);
+
+	/*
+	 * This is safe to do before the xpc_hb_checker thread has started
+	 * because the handler releases a wait queue.  If an interrupt is
+	 * received before the thread is waiting, it will not go to sleep,
+	 * but rather immediately process the interrupt.
+	 */
+	ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
+							"xpc hb", NULL);
+	if (ret != 0) {
+		dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
+			"errno=%d\n", -ret);
+
+		xpc_restrict_IPI_ops();
+
+		if (xpc_sysctl) {
+			unregister_sysctl_table(xpc_sysctl);
+		}
+		return -EBUSY;
+	}
+
+	/*
+	 * Fill the partition reserved page with the information needed by
+	 * other partitions to discover we are alive and establish initial
+	 * communications.
+	 */
+	xpc_rsvd_page = xpc_rsvd_page_init();
+	if (xpc_rsvd_page == NULL) {
+		dev_err(xpc_part, "could not setup our reserved page\n");
+
+		free_irq(SGI_XPC_ACTIVATE, NULL);
+		xpc_restrict_IPI_ops();
+
+		if (xpc_sysctl) {
+			unregister_sysctl_table(xpc_sysctl);
+		}
+		return -EBUSY;
+	}
+
+
+	/*
+	 * Set the beating to other partitions into motion.  This is
+	 * the last requirement for other partitions' discovery to
+	 * initiate communications with us.
+	 */
+	init_timer(&xpc_hb_timer);
+	xpc_hb_timer.function = xpc_hb_beater;
+	xpc_hb_beater(0);
+
+
+	/*
+	 * The real work-horse behind xpc.  This processes incoming
+	 * interrupts and monitors remote heartbeats.
+	 */
+	pid = kernel_thread(xpc_hb_checker, NULL, 0);
+	if (pid < 0) {
+		dev_err(xpc_part, "failed while forking hb check thread\n");
+
+		/* indicate to others that our reserved page is uninitialized */
+		xpc_rsvd_page->vars_pa = 0;
+
+		del_timer_sync(&xpc_hb_timer);
+		free_irq(SGI_XPC_ACTIVATE, NULL);
+		xpc_restrict_IPI_ops();
+
+		if (xpc_sysctl) {
+			unregister_sysctl_table(xpc_sysctl);
+		}
+		return -EBUSY;
+	}
+
+
+	/*
+	 * Startup a thread that will attempt to discover other partitions to
+	 * activate based on info provided by SAL. This new thread is short
+	 * lived and will exit once discovery is complete.
+	 */
+	pid = kernel_thread(xpc_initiate_discovery, NULL, 0);
+	if (pid < 0) {
+		dev_err(xpc_part, "failed while forking discovery thread\n");
+
+		/* mark this new thread as a non-starter */
+		up(&xpc_discovery_exited);
+
+		xpc_do_exit();
+		return -EBUSY;
+	}
+
+
+	/* set the interface to point at XPC's functions */
+	xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
+			  xpc_initiate_allocate, xpc_initiate_send,
+			  xpc_initiate_send_notify, xpc_initiate_received,
+			  xpc_initiate_partid_to_nasids);
+
+	return 0;
+}
+module_init(xpc_init);
+
+
+void __exit
+xpc_exit(void)
+{
+	xpc_do_exit();
+}
+module_exit(xpc_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
+MODULE_LICENSE("GPL");
+
+module_param(xpc_hb_interval, int, 0);
+MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
+		"heartbeat increments.");
+
+module_param(xpc_hb_check_interval, int, 0);
+MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
+		"heartbeat checks.");
+
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
new file mode 100644
index 0000000..2c3c4a8
--- /dev/null
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -0,0 +1,984 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) partition support.
+ *
+ *	This is the part of XPC that detects the presence/absence of
+ *	other partitions. It provides a heartbeat and monitors the
+ *	heartbeats of other partitions.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/sysctl.h>
+#include <linux/cache.h>
+#include <linux/mmzone.h>
+#include <linux/nodemask.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/addrs.h>
+#include "xpc.h"
+
+
+/* XPC is exiting flag */
+int xpc_exiting;
+
+
+/* SH_IPI_ACCESS shub register value on startup */
+static u64 xpc_sh1_IPI_access;
+static u64 xpc_sh2_IPI_access0;
+static u64 xpc_sh2_IPI_access1;
+static u64 xpc_sh2_IPI_access2;
+static u64 xpc_sh2_IPI_access3;
+
+
+/* original protection values for each node */
+u64 xpc_prot_vec[MAX_COMPACT_NODES];
+
+
+/* this partition's reserved page */
+struct xpc_rsvd_page *xpc_rsvd_page;
+
+/* this partition's XPC variables (within the reserved page) */
+struct xpc_vars *xpc_vars;
+struct xpc_vars_part *xpc_vars_part;
+
+
+/*
+ * For performance reasons, each entry of xpc_partitions[] is cacheline
+ * aligned. And xpc_partitions[] is padded with an additional entry at the
+ * end so that the last legitimate entry doesn't share its cacheline with
+ * another variable.
+ */
+struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+
+
+/*
+ * Generic buffer used to store a local copy of the remote partitions
+ * reserved page or XPC variables.
+ *
+ * xpc_discovery runs only once and is a seperate thread that is
+ * very likely going to be processing in parallel with receiving
+ * interrupts.
+ */
+char ____cacheline_aligned
+		xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE];
+
+
+/* systune related variables */
+int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
+int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_TIMEOUT;
+
+
+/*
+ * Given a nasid, get the physical address of the  partition's reserved page
+ * for that nasid. This function returns 0 on any error.
+ */
+static u64
+xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)
+{
+	bte_result_t bte_res;
+	s64 status;
+	u64 cookie = 0;
+	u64 rp_pa = nasid;	/* seed with nasid */
+	u64 len = 0;
+
+
+	while (1) {
+
+		status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,
+								&len);
+
+		dev_dbg(xpc_part, "SAL returned with status=%li, cookie="
+			"0x%016lx, address=0x%016lx, len=0x%016lx\n",
+			status, cookie, rp_pa, len);
+
+		if (status != SALRET_MORE_PASSES) {
+			break;
+		}
+
+		if (len > buf_size) {
+			dev_err(xpc_part, "len (=0x%016lx) > buf_size\n", len);
+			status = SALRET_ERROR;
+			break;
+		}
+
+		bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_size,
+					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+		if (bte_res != BTE_SUCCESS) {
+			dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
+			status = SALRET_ERROR;
+			break;
+		}
+	}
+
+	if (status != SALRET_OK) {
+		rp_pa = 0;
+	}
+	dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
+	return rp_pa;
+}
+
+
+/*
+ * Fill the partition reserved page with the information needed by
+ * other partitions to discover we are alive and establish initial
+ * communications.
+ */
+struct xpc_rsvd_page *
+xpc_rsvd_page_init(void)
+{
+	struct xpc_rsvd_page *rp;
+	AMO_t *amos_page;
+	u64 rp_pa, next_cl, nasid_array = 0;
+	int i, ret;
+
+
+	/* get the local reserved page's address */
+
+	rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),
+					(u64) xpc_remote_copy_buffer,
+						XPC_RSVD_PAGE_ALIGNED_SIZE);
+	if (rp_pa == 0) {
+		dev_err(xpc_part, "SAL failed to locate the reserved page\n");
+		return NULL;
+	}
+	rp = (struct xpc_rsvd_page *) __va(rp_pa);
+
+	if (rp->partid != sn_partition_id) {
+		dev_err(xpc_part, "the reserved page's partid of %d should be "
+			"%d\n", rp->partid, sn_partition_id);
+		return NULL;
+	}
+
+	rp->version = XPC_RP_VERSION;
+
+	/*
+	 * Place the XPC variables on the cache line following the
+	 * reserved page structure.
+	 */
+	next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE;
+	xpc_vars = (struct xpc_vars *) next_cl;
+
+	/*
+	 * Before clearing xpc_vars, see if a page of AMOs had been previously
+	 * allocated. If not we'll need to allocate one and set permissions
+	 * so that cross-partition AMOs are allowed.
+	 *
+	 * The allocated AMO page needs MCA reporting to remain disabled after
+	 * XPC has unloaded.  To make this work, we keep a copy of the pointer
+	 * to this page (i.e., amos_page) in the struct xpc_vars structure,
+	 * which is pointed to by the reserved page, and re-use that saved copy
+	 * on subsequent loads of XPC. This AMO page is never freed, and its
+	 * memory protections are never restricted.
+	 */
+	if ((amos_page = xpc_vars->amos_page) == NULL) {
+		amos_page = (AMO_t *) mspec_kalloc_page(0);
+		if (amos_page == NULL) {
+			dev_err(xpc_part, "can't allocate page of AMOs\n");
+			return NULL;
+		}
+
+		/*
+		 * Open up AMO-R/W to cpu.  This is done for Shub 1.1 systems
+		 * when xpc_allow_IPI_ops() is called via xpc_hb_init().
+		 */
+		if (!enable_shub_wars_1_1()) {
+			ret = sn_change_memprotect(ia64_tpa((u64) amos_page),
+					PAGE_SIZE, SN_MEMPROT_ACCESS_CLASS_1,
+					&nasid_array);
+			if (ret != 0) {
+				dev_err(xpc_part, "can't change memory "
+					"protections\n");
+				mspec_kfree_page((unsigned long) amos_page);
+				return NULL;
+			}
+		}
+	} else if (!IS_AMO_ADDRESS((u64) amos_page)) {
+		/*
+		 * EFI's XPBOOT can also set amos_page in the reserved page,
+		 * but it happens to leave it as an uncached physical address
+		 * and we need it to be an uncached virtual, so we'll have to
+		 * convert it.
+		 */
+		if (!IS_AMO_PHYS_ADDRESS((u64) amos_page)) {
+			dev_err(xpc_part, "previously used amos_page address "
+				"is bad = 0x%p\n", (void *) amos_page);
+			return NULL;
+		}
+		amos_page = (AMO_t *) TO_AMO((u64) amos_page);
+	}
+
+	memset(xpc_vars, 0, sizeof(struct xpc_vars));
+
+	/*
+	 * Place the XPC per partition specific variables on the cache line
+	 * following the XPC variables structure.
+	 */
+	next_cl += XPC_VARS_ALIGNED_SIZE;
+	memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *
+							XP_MAX_PARTITIONS);
+	xpc_vars_part = (struct xpc_vars_part *) next_cl;
+	xpc_vars->vars_part_pa = __pa(next_cl);
+
+	xpc_vars->version = XPC_V_VERSION;
+	xpc_vars->act_nasid = cpuid_to_nasid(0);
+	xpc_vars->act_phys_cpuid = cpu_physical_id(0);
+	xpc_vars->amos_page = amos_page;  /* save for next load of XPC */
+
+
+	/*
+	 * Initialize the activation related AMO variables.
+	 */
+	xpc_vars->act_amos = xpc_IPI_init(XP_MAX_PARTITIONS);
+	for (i = 1; i < XP_NASID_MASK_WORDS; i++) {
+		xpc_IPI_init(i + XP_MAX_PARTITIONS);
+	}
+	/* export AMO page's physical address to other partitions */
+	xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);
+
+	/*
+	 * This signifies to the remote partition that our reserved
+	 * page is initialized.
+	 */
+	(volatile u64) rp->vars_pa = __pa(xpc_vars);
+
+	return rp;
+}
+
+
+/*
+ * Change protections to allow IPI operations (and AMO operations on
+ * Shub 1.1 systems).
+ */
+void
+xpc_allow_IPI_ops(void)
+{
+	int node;
+	int nasid;
+
+
+	// >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+
+	if (is_shub2()) {
+		xpc_sh2_IPI_access0 =
+			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
+		xpc_sh2_IPI_access1 =
+			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
+		xpc_sh2_IPI_access2 =
+			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
+		xpc_sh2_IPI_access3 =
+			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
+
+		for_each_online_node(node) {
+			nasid = cnodeid_to_nasid(node);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+								-1UL);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+								-1UL);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+								-1UL);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+								-1UL);
+		}
+
+	} else {
+		xpc_sh1_IPI_access =
+			(u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
+
+		for_each_online_node(node) {
+			nasid = cnodeid_to_nasid(node);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+								-1UL);
+
+			/*
+			 * Since the BIST collides with memory operations on
+			 * SHUB 1.1 sn_change_memprotect() cannot be used.
+			 */
+			if (enable_shub_wars_1_1()) {
+				/* open up everything */
+				xpc_prot_vec[node] = (u64) HUB_L((u64 *)
+						GLOBAL_MMR_ADDR(nasid,
+						SH1_MD_DQLP_MMR_DIR_PRIVEC0));
+				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+						SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+								-1UL);
+				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+						SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+								-1UL);
+			}
+		}
+	}
+}
+
+
+/*
+ * Restrict protections to disallow IPI operations (and AMO operations on
+ * Shub 1.1 systems).
+ */
+void
+xpc_restrict_IPI_ops(void)
+{
+	int node;
+	int nasid;
+
+
+	// >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+
+	if (is_shub2()) {
+
+		for_each_online_node(node) {
+			nasid = cnodeid_to_nasid(node);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+							xpc_sh2_IPI_access0);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+							xpc_sh2_IPI_access1);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+							xpc_sh2_IPI_access2);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+							xpc_sh2_IPI_access3);
+		}
+
+	} else {
+
+		for_each_online_node(node) {
+			nasid = cnodeid_to_nasid(node);
+			HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+							xpc_sh1_IPI_access);
+
+			if (enable_shub_wars_1_1()) {
+				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+						SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+							xpc_prot_vec[node]);
+				HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+						SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+							xpc_prot_vec[node]);
+			}
+		}
+	}
+}
+
+
+/*
+ * At periodic intervals, scan through all active partitions and ensure
+ * their heartbeat is still active.  If not, the partition is deactivated.
+ */
+void
+xpc_check_remote_hb(void)
+{
+	struct xpc_vars *remote_vars;
+	struct xpc_partition *part;
+	partid_t partid;
+	bte_result_t bres;
+
+
+	remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+
+	for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+		if (partid == sn_partition_id) {
+			continue;
+		}
+
+		part = &xpc_partitions[partid];
+
+		if (part->act_state == XPC_P_INACTIVE ||
+				part->act_state == XPC_P_DEACTIVATING) {
+			continue;
+		}
+
+		/* pull the remote_hb cache line */
+		bres = xp_bte_copy(part->remote_vars_pa,
+					ia64_tpa((u64) remote_vars),
+					XPC_VARS_ALIGNED_SIZE,
+					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+		if (bres != BTE_SUCCESS) {
+			XPC_DEACTIVATE_PARTITION(part,
+						xpc_map_bte_errors(bres));
+			continue;
+		}
+
+		dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
+			" = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid,
+			remote_vars->heartbeat, part->last_heartbeat,
+			remote_vars->kdb_status,
+			remote_vars->heartbeating_to_mask);
+
+		if (((remote_vars->heartbeat == part->last_heartbeat) &&
+			(remote_vars->kdb_status == 0)) ||
+			     !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+
+			XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
+			continue;
+		}
+
+		part->last_heartbeat = remote_vars->heartbeat;
+	}
+}
+
+
+/*
+ * Get a copy of the remote partition's rsvd page.
+ *
+ * remote_rp points to a buffer that is cacheline aligned for BTE copies and
+ * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE.
+ */
+static enum xpc_retval
+xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
+		struct xpc_rsvd_page *remote_rp, u64 *remote_rsvd_page_pa)
+{
+	int bres, i;
+
+
+	/* get the reserved page's physical address */
+
+	*remote_rsvd_page_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,
+						XPC_RSVD_PAGE_ALIGNED_SIZE);
+	if (*remote_rsvd_page_pa == 0) {
+		return xpcNoRsvdPageAddr;
+	}
+
+
+	/* pull over the reserved page structure */
+
+	bres = xp_bte_copy(*remote_rsvd_page_pa, ia64_tpa((u64) remote_rp),
+				XPC_RSVD_PAGE_ALIGNED_SIZE,
+				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+	if (bres != BTE_SUCCESS) {
+		return xpc_map_bte_errors(bres);
+	}
+
+
+	if (discovered_nasids != NULL) {
+		for (i = 0; i < XP_NASID_MASK_WORDS; i++) {
+			discovered_nasids[i] |= remote_rp->part_nasids[i];
+		}
+	}
+
+
+	/* check that the partid is for another partition */
+
+	if (remote_rp->partid < 1 ||
+				remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {
+		return xpcInvalidPartid;
+	}
+
+	if (remote_rp->partid == sn_partition_id) {
+		return xpcLocalPartid;
+	}
+
+
+	if (XPC_VERSION_MAJOR(remote_rp->version) !=
+					XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
+		return xpcBadVersion;
+	}
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Get a copy of the remote partition's XPC variables.
+ *
+ * remote_vars points to a buffer that is cacheline aligned for BTE copies and
+ * assumed to be of size XPC_VARS_ALIGNED_SIZE.
+ */
+static enum xpc_retval
+xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
+{
+	int bres;
+
+
+	if (remote_vars_pa == 0) {
+		return xpcVarsNotSet;
+	}
+
+
+	/* pull over the cross partition variables */
+
+	bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
+				XPC_VARS_ALIGNED_SIZE,
+				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+	if (bres != BTE_SUCCESS) {
+		return xpc_map_bte_errors(bres);
+	}
+
+	if (XPC_VERSION_MAJOR(remote_vars->version) !=
+					XPC_VERSION_MAJOR(XPC_V_VERSION)) {
+		return xpcBadVersion;
+	}
+
+	return xpcSuccess;
+}
+
+
+/*
+ * Prior code has determine the nasid which generated an IPI.  Inspect
+ * that nasid to determine if its partition needs to be activated or
+ * deactivated.
+ *
+ * A partition is consider "awaiting activation" if our partition
+ * flags indicate it is not active and it has a heartbeat.  A
+ * partition is considered "awaiting deactivation" if our partition
+ * flags indicate it is active but it has no heartbeat or it is not
+ * sending its heartbeat to us.
+ *
+ * To determine the heartbeat, the remote nasid must have a properly
+ * initialized reserved page.
+ */
+static void
+xpc_identify_act_IRQ_req(int nasid)
+{
+	struct xpc_rsvd_page *remote_rp;
+	struct xpc_vars *remote_vars;
+	u64 remote_rsvd_page_pa;
+	u64 remote_vars_pa;
+	partid_t partid;
+	struct xpc_partition *part;
+	enum xpc_retval ret;
+
+
+	/* pull over the reserved page structure */
+
+	remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;
+
+	ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rsvd_page_pa);
+	if (ret != xpcSuccess) {
+		dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
+			"which sent interrupt, reason=%d\n", nasid, ret);
+		return;
+	}
+
+	remote_vars_pa = remote_rp->vars_pa;
+	partid = remote_rp->partid;
+	part = &xpc_partitions[partid];
+
+
+	/* pull over the cross partition variables */
+
+	remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+
+	ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+	if (ret != xpcSuccess) {
+
+		dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
+			"which sent interrupt, reason=%d\n", nasid, ret);
+
+		XPC_DEACTIVATE_PARTITION(part, ret);
+		return;
+	}
+
+
+	part->act_IRQ_rcvd++;
+
+	dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
+		"%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,
+		remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
+
+
+	if (part->act_state == XPC_P_INACTIVE) {
+
+		part->remote_rp_pa = remote_rsvd_page_pa;
+		dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n",
+			part->remote_rp_pa);
+
+		part->remote_vars_pa = remote_vars_pa;
+		dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
+			part->remote_vars_pa);
+
+		part->last_heartbeat = remote_vars->heartbeat;
+		dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
+			part->last_heartbeat);
+
+		part->remote_vars_part_pa = remote_vars->vars_part_pa;
+		dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
+			part->remote_vars_part_pa);
+
+		part->remote_act_nasid = remote_vars->act_nasid;
+		dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
+			part->remote_act_nasid);
+
+		part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
+		dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
+			part->remote_act_phys_cpuid);
+
+		part->remote_amos_page_pa = remote_vars->amos_page_pa;
+		dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
+			part->remote_amos_page_pa);
+
+		xpc_activate_partition(part);
+
+	} else if (part->remote_amos_page_pa != remote_vars->amos_page_pa ||
+			!XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+
+		part->reactivate_nasid = nasid;
+		XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+	}
+}
+
+
+/*
+ * Loop through the activation AMO variables and process any bits
+ * which are set.  Each bit indicates a nasid sending a partition
+ * activation or deactivation request.
+ *
+ * Return #of IRQs detected.
+ */
+int
+xpc_identify_act_IRQ_sender(void)
+{
+	int word, bit;
+	u64 nasid_mask;
+	u64 nasid;			/* remote nasid */
+	int n_IRQs_detected = 0;
+	AMO_t *act_amos;
+	struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
+
+
+	act_amos = xpc_vars->act_amos;
+
+
+	/* scan through act AMO variable looking for non-zero entries */
+	for (word = 0; word < XP_NASID_MASK_WORDS; word++) {
+
+		nasid_mask = xpc_IPI_receive(&act_amos[word]);
+		if (nasid_mask == 0) {
+			/* no IRQs from nasids in this variable */
+			continue;
+		}
+
+		dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
+			nasid_mask);
+
+
+		/*
+		 * If this nasid has been added to the machine since
+		 * our partition was reset, this will retain the
+		 * remote nasid in our reserved pages machine mask.
+		 * This is used in the event of module reload.
+		 */
+		rp->mach_nasids[word] |= nasid_mask;
+
+
+		/* locate the nasid(s) which sent interrupts */
+
+		for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
+			if (nasid_mask & (1UL << bit)) {
+				n_IRQs_detected++;
+				nasid = XPC_NASID_FROM_W_B(word, bit);
+				dev_dbg(xpc_part, "interrupt from nasid %ld\n",
+					nasid);
+				xpc_identify_act_IRQ_req(nasid);
+			}
+		}
+	}
+	return n_IRQs_detected;
+}
+
+
+/*
+ * Mark specified partition as active.
+ */
+enum xpc_retval
+xpc_mark_partition_active(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+	enum xpc_retval ret;
+
+
+	dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
+
+	spin_lock_irqsave(&part->act_lock, irq_flags);
+	if (part->act_state == XPC_P_ACTIVATING) {
+		part->act_state = XPC_P_ACTIVE;
+		ret = xpcSuccess;
+	} else {
+		DBUG_ON(part->reason == xpcSuccess);
+		ret = part->reason;
+	}
+	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+	return ret;
+}
+
+
+/*
+ * Notify XPC that the partition is down.
+ */
+void
+xpc_deactivate_partition(const int line, struct xpc_partition *part,
+				enum xpc_retval reason)
+{
+	unsigned long irq_flags;
+	partid_t partid = XPC_PARTID(part);
+
+
+	spin_lock_irqsave(&part->act_lock, irq_flags);
+
+	if (part->act_state == XPC_P_INACTIVE) {
+		XPC_SET_REASON(part, reason, line);
+		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+		if (reason == xpcReactivating) {
+			/* we interrupt ourselves to reactivate partition */
+			xpc_IPI_send_reactivate(part);
+		}
+		return;
+	}
+	if (part->act_state == XPC_P_DEACTIVATING) {
+		if ((part->reason == xpcUnloading && reason != xpcUnloading) ||
+					reason == xpcReactivating) {
+			XPC_SET_REASON(part, reason, line);
+		}
+		spin_unlock_irqrestore(&part->act_lock, irq_flags);
+		return;
+	}
+
+	part->act_state = XPC_P_DEACTIVATING;
+	XPC_SET_REASON(part, reason, line);
+
+	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+	XPC_DISALLOW_HB(partid, xpc_vars);
+
+	dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n", partid,
+		reason);
+
+	xpc_partition_down(part, reason);
+}
+
+
+/*
+ * Mark specified partition as active.
+ */
+void
+xpc_mark_partition_inactive(struct xpc_partition *part)
+{
+	unsigned long irq_flags;
+
+
+	dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
+		XPC_PARTID(part));
+
+	spin_lock_irqsave(&part->act_lock, irq_flags);
+	part->act_state = XPC_P_INACTIVE;
+	spin_unlock_irqrestore(&part->act_lock, irq_flags);
+	part->remote_rp_pa = 0;
+}
+
+
+/*
+ * SAL has provided a partition and machine mask.  The partition mask
+ * contains a bit for each even nasid in our partition.  The machine
+ * mask contains a bit for each even nasid in the entire machine.
+ *
+ * Using those two bit arrays, we can determine which nasids are
+ * known in the machine.  Each should also have a reserved page
+ * initialized if they are available for partitioning.
+ */
+void
+xpc_discovery(void)
+{
+	void *remote_rp_base;
+	struct xpc_rsvd_page *remote_rp;
+	struct xpc_vars *remote_vars;
+	u64 remote_rsvd_page_pa;
+	u64 remote_vars_pa;
+	int region;
+	int max_regions;
+	int nasid;
+	struct xpc_rsvd_page *rp;
+	partid_t partid;
+	struct xpc_partition *part;
+	u64 *discovered_nasids;
+	enum xpc_retval ret;
+
+
+	remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE,
+						GFP_KERNEL, &remote_rp_base);
+	if (remote_rp == NULL) {
+		return;
+	}
+	remote_vars = (struct xpc_vars *) remote_rp;
+
+
+	discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS,
+							GFP_KERNEL);
+	if (discovered_nasids == NULL) {
+		kfree(remote_rp_base);
+		return;
+	}
+	memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS);
+
+	rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
+
+	/*
+	 * The term 'region' in this context refers to the minimum number of
+	 * nodes that can comprise an access protection grouping. The access
+	 * protection is in regards to memory, IOI and IPI.
+	 */
+//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or
+//>>> include/asm-ia64/sn/addrs.h
+#define SH1_MAX_REGIONS		64
+#define SH2_MAX_REGIONS		256
+	max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS;
+
+	for (region = 0; region < max_regions; region++) {
+
+		if ((volatile int) xpc_exiting) {
+			break;
+		}
+
+		dev_dbg(xpc_part, "searching region %d\n", region);
+
+		for (nasid = (region * sn_region_size * 2);
+		     nasid < ((region + 1) * sn_region_size * 2);
+		     nasid += 2) {
+
+			if ((volatile int) xpc_exiting) {
+				break;
+			}
+
+			dev_dbg(xpc_part, "checking nasid %d\n", nasid);
+
+
+			if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) {
+				dev_dbg(xpc_part, "PROM indicates Nasid %d is "
+					"part of the local partition; skipping "
+					"region\n", nasid);
+				break;
+			}
+
+			if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) {
+				dev_dbg(xpc_part, "PROM indicates Nasid %d was "
+					"not on Numa-Link network at reset\n",
+					nasid);
+				continue;
+			}
+
+			if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {
+				dev_dbg(xpc_part, "Nasid %d is part of a "
+					"partition which was previously "
+					"discovered\n", nasid);
+				continue;
+			}
+
+
+			/* pull over the reserved page structure */
+
+			ret = xpc_get_remote_rp(nasid, discovered_nasids,
+					      remote_rp, &remote_rsvd_page_pa);
+			if (ret != xpcSuccess) {
+				dev_dbg(xpc_part, "unable to get reserved page "
+					"from nasid %d, reason=%d\n", nasid,
+					ret);
+
+				if (ret == xpcLocalPartid) {
+					break;
+				}
+				continue;
+			}
+
+			remote_vars_pa = remote_rp->vars_pa;
+
+			partid = remote_rp->partid;
+			part = &xpc_partitions[partid];
+
+
+			/* pull over the cross partition variables */
+
+			ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+			if (ret != xpcSuccess) {
+				dev_dbg(xpc_part, "unable to get XPC variables "
+					"from nasid %d, reason=%d\n", nasid,
+					ret);
+
+				XPC_DEACTIVATE_PARTITION(part, ret);
+				continue;
+			}
+
+			if (part->act_state != XPC_P_INACTIVE) {
+				dev_dbg(xpc_part, "partition %d on nasid %d is "
+					"already activating\n", partid, nasid);
+				break;
+			}
+
+			/*
+			 * Register the remote partition's AMOs with SAL so it
+			 * can handle and cleanup errors within that address
+			 * range should the remote partition go down. We don't
+			 * unregister this range because it is difficult to
+			 * tell when outstanding writes to the remote partition
+			 * are finished and thus when it is thus safe to
+			 * unregister. This should not result in wasted space
+			 * in the SAL xp_addr_region table because we should
+			 * get the same page for remote_act_amos_pa after
+			 * module reloads and system reboots.
+			 */
+			if (sn_register_xp_addr_region(
+					    remote_vars->amos_page_pa,
+							PAGE_SIZE, 1) < 0) {
+				dev_dbg(xpc_part, "partition %d failed to "
+					"register xp_addr region 0x%016lx\n",
+					partid, remote_vars->amos_page_pa);
+
+				XPC_SET_REASON(part, xpcPhysAddrRegFailed,
+						__LINE__);
+				break;
+			}
+
+			/*
+			 * The remote nasid is valid and available.
+			 * Send an interrupt to that nasid to notify
+			 * it that we are ready to begin activation.
+			 */
+			dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "
+				"nasid %d, phys_cpuid 0x%x\n",
+				remote_vars->amos_page_pa,
+				remote_vars->act_nasid,
+				remote_vars->act_phys_cpuid);
+
+			xpc_IPI_send_activate(remote_vars);
+		}
+	}
+
+	kfree(discovered_nasids);
+	kfree(remote_rp_base);
+}
+
+
+/*
+ * Given a partid, get the nasids owned by that partition from the
+ * remote partition's reserved page.
+ */
+enum xpc_retval
+xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
+{
+	struct xpc_partition *part;
+	u64 part_nasid_pa;
+	int bte_res;
+
+
+	part = &xpc_partitions[partid];
+	if (part->remote_rp_pa == 0) {
+		return xpcPartitionDown;
+	}
+
+	part_nasid_pa = part->remote_rp_pa +
+		(u64) &((struct xpc_rsvd_page *) 0)->part_nasids;
+
+	bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
+				L1_CACHE_ALIGN(XP_NASID_MASK_BYTES),
+				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
+
+	return xpc_map_bte_errors(bte_res);
+}
+
diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
new file mode 100644
index 0000000..78c13d6
--- /dev/null
+++ b/arch/ia64/sn/kernel/xpnet.c
@@ -0,0 +1,715 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+/*
+ * Cross Partition Network Interface (XPNET) support
+ *
+ *	XPNET provides a virtual network layered on top of the Cross
+ *	Partition communication layer.
+ *
+ *	XPNET provides direct point-to-point and broadcast-like support
+ *	for an ethernet-like device.  The ethernet broadcast medium is
+ *	replaced with a point-to-point message structure which passes
+ *	pointers to a DMA-capable block that a remote partition should
+ *	retrieve and pass to the upper level networking layer.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/types.h>
+#include <asm/atomic.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * The message payload transferred by XPC.
+ *
+ * buf_pa is the physical address where the DMA should pull from.
+ *
+ * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
+ * cacheline boundary.  To accomplish this, we record the number of
+ * bytes from the beginning of the first cacheline to the first useful
+ * byte of the skb (leadin_ignore) and the number of bytes from the
+ * last useful byte of the skb to the end of the last cacheline
+ * (tailout_ignore).
+ *
+ * size is the number of bytes to transfer which includes the skb->len
+ * (useful bytes of the senders skb) plus the leadin and tailout
+ */
+struct xpnet_message {
+	u16 version;		/* Version for this message */
+	u16 embedded_bytes;	/* #of bytes embedded in XPC message */
+	u32 magic;		/* Special number indicating this is xpnet */
+	u64 buf_pa;		/* phys address of buffer to retrieve */
+	u32 size;		/* #of bytes in buffer */
+	u8 leadin_ignore;	/* #of bytes to ignore at the beginning */
+	u8 tailout_ignore;	/* #of bytes to ignore at the end */
+	unsigned char data;	/* body of small packets */
+};
+
+/*
+ * Determine the size of our message, the cacheline aligned size,
+ * and then the number of message will request from XPC.
+ *
+ * XPC expects each message to exist in an individual cacheline.
+ */
+#define XPNET_MSG_SIZE		(L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)
+#define XPNET_MSG_DATA_MAX	\
+		(XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))
+#define XPNET_MSG_ALIGNED_SIZE	(L1_CACHE_ALIGN(XPNET_MSG_SIZE))
+#define XPNET_MSG_NENTRIES	(PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
+
+
+#define XPNET_MAX_KTHREADS	(XPNET_MSG_NENTRIES + 1)
+#define XPNET_MAX_IDLE_KTHREADS	(XPNET_MSG_NENTRIES + 1)
+
+/*
+ * Version number of XPNET implementation. XPNET can always talk to versions
+ * with same major #, and never talk to versions with a different version.
+ */
+#define _XPNET_VERSION(_major, _minor)	(((_major) << 4) | (_minor))
+#define XPNET_VERSION_MAJOR(_v)		((_v) >> 4)
+#define XPNET_VERSION_MINOR(_v)		((_v) & 0xf)
+
+#define	XPNET_VERSION _XPNET_VERSION(1,0)		/* version 1.0 */
+#define	XPNET_VERSION_EMBED _XPNET_VERSION(1,1)		/* version 1.1 */
+#define XPNET_MAGIC	0x88786984 /* "XNET" */
+
+#define XPNET_VALID_MSG(_m)						     \
+   ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
+    && (msg->magic == XPNET_MAGIC))
+
+#define XPNET_DEVICE_NAME		"xp0"
+
+
+/*
+ * When messages are queued with xpc_send_notify, a kmalloc'd buffer
+ * of the following type is passed as a notification cookie.  When the
+ * notification function is called, we use the cookie to decide
+ * whether all outstanding message sends have completed.  The skb can
+ * then be released.
+ */
+struct xpnet_pending_msg {
+	struct list_head free_list;
+	struct sk_buff *skb;
+	atomic_t use_count;
+};
+
+/* driver specific structure pointed to by the device structure */
+struct xpnet_dev_private {
+	struct net_device_stats stats;
+};
+
+struct net_device *xpnet_device;
+
+/*
+ * When we are notified of other partitions activating, we add them to
+ * our bitmask of partitions to which we broadcast.
+ */
+static u64 xpnet_broadcast_partitions;
+/* protect above */
+static spinlock_t xpnet_broadcast_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Since the Block Transfer Engine (BTE) is being used for the transfer
+ * and it relies upon cache-line size transfers, we need to reserve at
+ * least one cache-line for head and tail alignment.  The BTE is
+ * limited to 8MB transfers.
+ *
+ * Testing has shown that changing MTU to greater than 64KB has no effect
+ * on TCP as the two sides negotiate a Max Segment Size that is limited
+ * to 64K.  Other protocols May use packets greater than this, but for
+ * now, the default is 64KB.
+ */
+#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+/* 32KB has been determined to be the ideal */
+#define XPNET_DEF_MTU (0x8000UL)
+
+
+/*
+ * The partition id is encapsulated in the MAC address.  The following
+ * define locates the octet the partid is in.
+ */
+#define XPNET_PARTID_OCTET	1
+#define XPNET_LICENSE_OCTET	2
+
+
+/*
+ * Define the XPNET debug device structure that is to be used with dev_dbg(),
+ * dev_err(), dev_warn(), and dev_info().
+ */
+struct device_driver xpnet_dbg_name = {
+	.name = "xpnet"
+};
+
+struct device xpnet_dbg_subname = {
+	.bus_id = {0},			/* set to "" */
+	.driver = &xpnet_dbg_name
+};
+
+struct device *xpnet = &xpnet_dbg_subname;
+
+/*
+ * Packet was recevied by XPC and forwarded to us.
+ */
+static void
+xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
+{
+	struct sk_buff *skb;
+	bte_result_t bret;
+	struct xpnet_dev_private *priv =
+		(struct xpnet_dev_private *) xpnet_device->priv;
+
+
+	if (!XPNET_VALID_MSG(msg)) {
+		/*
+		 * Packet with a different XPC version.  Ignore.
+		 */
+		xpc_received(partid, channel, (void *) msg);
+
+		priv->stats.rx_errors++;
+
+		return;
+	}
+	dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
+		msg->leadin_ignore, msg->tailout_ignore);
+
+
+	/* reserve an extra cache line */
+	skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
+	if (!skb) {
+		dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
+			msg->size + L1_CACHE_BYTES);
+
+		xpc_received(partid, channel, (void *) msg);
+
+		priv->stats.rx_errors++;
+
+		return;
+	}
+
+	/*
+	 * The allocated skb has some reserved space.
+	 * In order to use bte_copy, we need to get the
+	 * skb->data pointer moved forward.
+	 */
+	skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
+					    (L1_CACHE_BYTES - 1)) +
+			  msg->leadin_ignore));
+
+	/*
+	 * Update the tail pointer to indicate data actually
+	 * transferred.
+	 */
+	skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
+
+	/*
+	 * Move the data over from the the other side.
+	 */
+	if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
+						(msg->embedded_bytes != 0)) {
+		dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
+			"%lu)\n", skb->data, &msg->data,
+			(size_t) msg->embedded_bytes);
+
+		memcpy(skb->data, &msg->data, (size_t) msg->embedded_bytes);
+	} else {
+		dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
+			"bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,
+			(void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+			msg->size);
+
+		bret = bte_copy(msg->buf_pa,
+				__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+				msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+
+		if (bret != BTE_SUCCESS) {
+			// >>> Need better way of cleaning skb.  Currently skb
+			// >>> appears in_use and we can't just call
+			// >>> dev_kfree_skb.
+			dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "
+				"error=0x%x\n", (void *)msg->buf_pa,
+				(void *)__pa((u64)skb->data &
+							~(L1_CACHE_BYTES - 1)),
+				msg->size, bret);
+
+			xpc_received(partid, channel, (void *) msg);
+
+			priv->stats.rx_errors++;
+
+			return;
+		}
+	}
+
+	dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+		"skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+		(void *) skb->data, (void *) skb->tail, (void *) skb->end,
+		skb->len);
+
+	skb->dev = xpnet_device;
+	skb->protocol = eth_type_trans(skb, xpnet_device);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	dev_dbg(xpnet, "passing skb to network layer; \n\tskb->head=0x%p "
+		"skb->data=0x%p skb->tail=0x%p skb->end=0x%p skb->len=%d\n",
+		(void *) skb->head, (void *) skb->data, (void *) skb->tail,
+		(void *) skb->end, skb->len);
+
+
+	xpnet_device->last_rx = jiffies;
+	priv->stats.rx_packets++;
+	priv->stats.rx_bytes += skb->len + ETH_HLEN;
+
+	netif_rx_ni(skb);
+	xpc_received(partid, channel, (void *) msg);
+}
+
+
+/*
+ * This is the handler which XPC calls during any sort of change in
+ * state or message reception on a connection.
+ */
+static void
+xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,
+			  void *data, void *key)
+{
+	long bp;
+
+
+	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+	DBUG_ON(channel != XPC_NET_CHANNEL);
+
+	switch(reason) {
+	case xpcMsgReceived:	/* message received */
+		DBUG_ON(data == NULL);
+
+		xpnet_receive(partid, channel, (struct xpnet_message *) data);
+		break;
+
+	case xpcConnected:	/* connection completed to a partition */
+		spin_lock_bh(&xpnet_broadcast_lock);
+		xpnet_broadcast_partitions |= 1UL << (partid -1 );
+		bp = xpnet_broadcast_partitions;
+		spin_unlock_bh(&xpnet_broadcast_lock);
+
+		netif_carrier_on(xpnet_device);
+
+		dev_dbg(xpnet, "%s connection created to partition %d; "
+			"xpnet_broadcast_partitions=0x%lx\n",
+			xpnet_device->name, partid, bp);
+		break;
+
+	default:
+		spin_lock_bh(&xpnet_broadcast_lock);
+		xpnet_broadcast_partitions &= ~(1UL << (partid -1 ));
+		bp = xpnet_broadcast_partitions;
+		spin_unlock_bh(&xpnet_broadcast_lock);
+
+		if (bp == 0) {
+			netif_carrier_off(xpnet_device);
+		}
+
+		dev_dbg(xpnet, "%s disconnected from partition %d; "
+			"xpnet_broadcast_partitions=0x%lx\n",
+			xpnet_device->name, partid, bp);
+		break;
+
+	}
+}
+
+
+static int
+xpnet_dev_open(struct net_device *dev)
+{
+	enum xpc_retval ret;
+
+
+	dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %d, "
+		"%d)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
+		XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,
+		XPNET_MAX_IDLE_KTHREADS);
+
+	ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
+			  XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
+			  XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
+	if (ret != xpcSuccess) {
+		dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
+			"ret=%d\n", dev->name, ret);
+
+		return -ENOMEM;
+	}
+
+	dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
+
+	return 0;
+}
+
+
+static int
+xpnet_dev_stop(struct net_device *dev)
+{
+	xpc_disconnect(XPC_NET_CHANNEL);
+
+	dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
+
+	return 0;
+}
+
+
+static int
+xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
+{
+	/* 68 comes from min TCP+IP+MAC header */
+	if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
+		dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
+			"between 68 and %ld\n", dev->name, new_mtu,
+			XPNET_MAX_MTU);
+		return -EINVAL;
+	}
+
+	dev->mtu = new_mtu;
+	dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
+	return 0;
+}
+
+
+/*
+ * Required for the net_device structure.
+ */
+static int
+xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
+{
+	return 0;
+}
+
+
+/*
+ * Return statistics to the caller.
+ */
+static struct net_device_stats *
+xpnet_dev_get_stats(struct net_device *dev)
+{
+	struct xpnet_dev_private *priv;
+
+
+	priv = (struct xpnet_dev_private *) dev->priv;
+
+	return &priv->stats;
+}
+
+
+/*
+ * Notification that the other end has received the message and
+ * DMA'd the skb information.  At this point, they are done with
+ * our side.  When all recipients are done processing, we
+ * release the skb and then release our pending message structure.
+ */
+static void
+xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,
+			void *__qm)
+{
+	struct xpnet_pending_msg *queued_msg =
+		(struct xpnet_pending_msg *) __qm;
+
+
+	DBUG_ON(queued_msg == NULL);
+
+	dev_dbg(xpnet, "message to %d notified with reason %d\n",
+		partid, reason);
+
+	if (atomic_dec_return(&queued_msg->use_count) == 0) {
+		dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
+			(void *) queued_msg->skb->head);
+
+		dev_kfree_skb_any(queued_msg->skb);
+		kfree(queued_msg);
+	}
+}
+
+
+/*
+ * Network layer has formatted a packet (skb) and is ready to place it
+ * "on the wire".  Prepare and send an xpnet_message to all partitions
+ * which have connected with us and are targets of this packet.
+ *
+ * MAC-NOTE:  For the XPNET driver, the MAC address contains the
+ * destination partition_id.  If the destination partition id word
+ * is 0xff, this packet is to broadcast to all partitions.
+ */
+static int
+xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct xpnet_pending_msg *queued_msg;
+	enum xpc_retval ret;
+	struct xpnet_message *msg;
+	u64 start_addr, end_addr;
+	long dp;
+	u8 second_mac_octet;
+	partid_t dest_partid;
+	struct xpnet_dev_private *priv;
+	u16 embedded_bytes;
+
+
+	priv = (struct xpnet_dev_private *) dev->priv;
+
+
+	dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+		"skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+		(void *) skb->data, (void *) skb->tail, (void *) skb->end,
+		skb->len);
+
+
+	/*
+	 * The xpnet_pending_msg tracks how many outstanding
+	 * xpc_send_notifies are relying on this skb.  When none
+	 * remain, release the skb.
+	 */
+	queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);
+	if (queued_msg == NULL) {
+		dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
+			"packet\n", sizeof(struct xpnet_pending_msg));
+
+		priv->stats.tx_errors++;
+
+		return -ENOMEM;
+	}
+
+
+	/* get the beginning of the first cacheline and end of last */
+	start_addr = ((u64) skb->data & ~(L1_CACHE_BYTES - 1));
+	end_addr = L1_CACHE_ALIGN((u64) skb->tail);
+
+	/* calculate how many bytes to embed in the XPC message */
+	embedded_bytes = 0;
+	if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
+		/* skb->data does fit so embed */
+		embedded_bytes = skb->len;
+	}
+
+
+	/*
+	 * Since the send occurs asynchronously, we set the count to one
+	 * and begin sending.  Any sends that happen to complete before
+	 * we are done sending will not free the skb.  We will be left
+	 * with that task during exit.  This also handles the case of
+	 * a packet destined for a partition which is no longer up.
+	 */
+	atomic_set(&queued_msg->use_count, 1);
+	queued_msg->skb = skb;
+
+
+	second_mac_octet = skb->data[XPNET_PARTID_OCTET];
+	if (second_mac_octet == 0xff) {
+		/* we are being asked to broadcast to all partitions */
+		dp = xpnet_broadcast_partitions;
+	} else if (second_mac_octet != 0) {
+		dp = xpnet_broadcast_partitions &
+					(1UL << (second_mac_octet - 1));
+	} else {
+		/* 0 is an invalid partid.  Ignore */
+		dp = 0;
+	}
+	dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);
+
+	/*
+	 * If we wanted to allow promiscous mode to work like an
+	 * unswitched network, this would be a good point to OR in a
+	 * mask of partitions which should be receiving all packets.
+	 */
+
+	/*
+	 * Main send loop.
+	 */
+	for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;
+	     dest_partid++) {
+
+
+		if (!(dp & (1UL << (dest_partid - 1)))) {
+			/* not destined for this partition */
+			continue;
+		}
+
+		/* remove this partition from the destinations mask */
+		dp &= ~(1UL << (dest_partid - 1));
+
+
+		/* found a partition to send to */
+
+		ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,
+				   XPC_NOWAIT, (void **)&msg);
+		if (unlikely(ret != xpcSuccess)) {
+			continue;
+		}
+
+		msg->embedded_bytes = embedded_bytes;
+		if (unlikely(embedded_bytes != 0)) {
+			msg->version = XPNET_VERSION_EMBED;
+			dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
+				&msg->data, skb->data, (size_t) embedded_bytes);
+			memcpy(&msg->data, skb->data, (size_t) embedded_bytes);
+		} else {
+			msg->version = XPNET_VERSION;
+		}
+		msg->magic = XPNET_MAGIC;
+		msg->size = end_addr - start_addr;
+		msg->leadin_ignore = (u64) skb->data - start_addr;
+		msg->tailout_ignore = end_addr - (u64) skb->tail;
+		msg->buf_pa = __pa(start_addr);
+
+		dev_dbg(xpnet, "sending XPC message to %d:%d\nmsg->buf_pa="
+			"0x%lx, msg->size=%u, msg->leadin_ignore=%u, "
+			"msg->tailout_ignore=%u\n", dest_partid,
+			XPC_NET_CHANNEL, msg->buf_pa, msg->size,
+			msg->leadin_ignore, msg->tailout_ignore);
+
+
+		atomic_inc(&queued_msg->use_count);
+
+		ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,
+				      xpnet_send_completed, queued_msg);
+		if (unlikely(ret != xpcSuccess)) {
+			atomic_dec(&queued_msg->use_count);
+			continue;
+		}
+
+	}
+
+	if (atomic_dec_return(&queued_msg->use_count) == 0) {
+		dev_dbg(xpnet, "no partitions to receive packet destined for "
+			"%d\n", dest_partid);
+
+
+		dev_kfree_skb(skb);
+		kfree(queued_msg);
+	}
+
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes += skb->len;
+
+	return 0;
+}
+
+
+/*
+ * Deal with transmit timeouts coming from the network layer.
+ */
+static void
+xpnet_dev_tx_timeout (struct net_device *dev)
+{
+	struct xpnet_dev_private *priv;
+
+
+	priv = (struct xpnet_dev_private *) dev->priv;
+
+	priv->stats.tx_errors++;
+	return;
+}
+
+
+static int __init
+xpnet_init(void)
+{
+	int i;
+	u32 license_num;
+	int result = -ENOMEM;
+
+
+	dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
+
+	/*
+	 * use ether_setup() to init the majority of our device
+	 * structure and then override the necessary pieces.
+	 */
+	xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
+				    XPNET_DEVICE_NAME, ether_setup);
+	if (xpnet_device == NULL) {
+		return -ENOMEM;
+	}
+
+	netif_carrier_off(xpnet_device);
+
+	xpnet_device->mtu = XPNET_DEF_MTU;
+	xpnet_device->change_mtu = xpnet_dev_change_mtu;
+	xpnet_device->open = xpnet_dev_open;
+	xpnet_device->get_stats = xpnet_dev_get_stats;
+	xpnet_device->stop = xpnet_dev_stop;
+	xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
+	xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
+	xpnet_device->set_config = xpnet_dev_set_config;
+
+	/*
+	 * Multicast assumes the LSB of the first octet is set for multicast
+	 * MAC addresses.  We chose the first octet of the MAC to be unlikely
+	 * to collide with any vendor's officially issued MAC.
+	 */
+	xpnet_device->dev_addr[0] = 0xfe;
+	xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;
+	license_num = sn_partition_serial_number_val();
+	for (i = 3; i >= 0; i--) {
+		xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =
+							license_num & 0xff;
+		license_num = license_num >> 8;
+	}
+
+	/*
+	 * ether_setup() sets this to a multicast device.  We are
+	 * really not supporting multicast at this time.
+	 */
+	xpnet_device->flags &= ~IFF_MULTICAST;
+
+	/*
+	 * No need to checksum as it is a DMA transfer.  The BTE will
+	 * report an error if the data is not retrievable and the
+	 * packet will be dropped.
+	 */
+	xpnet_device->features = NETIF_F_NO_CSUM;
+
+	result = register_netdev(xpnet_device);
+	if (result != 0) {
+		free_netdev(xpnet_device);
+	}
+
+	return result;
+}
+module_init(xpnet_init);
+
+
+static void __exit
+xpnet_exit(void)
+{
+	dev_info(xpnet, "unregistering network device %s\n",
+		xpnet_device[0].name);
+
+	unregister_netdev(xpnet_device);
+
+	free_netdev(xpnet_device);
+}
+module_exit(xpnet_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
index b5dca00..2f915bc 100644
--- a/arch/ia64/sn/pci/Makefile
+++ b/arch/ia64/sn/pci/Makefile
@@ -7,4 +7,4 @@
 #
 # Makefile for the sn pci general routines.
 
-obj-y := pci_dma.o pcibr/ 
+obj-y := pci_dma.o tioca_provider.o pcibr/ 
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index f680824..5da9bdb 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -12,9 +12,8 @@
 #include <linux/module.h>
 #include <asm/dma.h>
 #include <asm/sn/sn_sal.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
-#include "pci/pcibr_provider.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 
 #define SG_ENT_VIRT_ADDRESS(sg)	(page_address((sg)->page) + (sg)->offset)
 #define SG_ENT_PHYS_ADDRESS(SG)	virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
@@ -79,7 +78,8 @@
 {
 	void *cpuaddr;
 	unsigned long phys_addr;
-	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
 	BUG_ON(dev->bus != &pci_bus_type);
 
@@ -102,8 +102,7 @@
 	 * resources.
 	 */
 
-	*dma_handle = pcibr_dma_map(pcidev_info, phys_addr, size,
-				    SN_PCIDMA_CONSISTENT);
+	*dma_handle = provider->dma_map_consistent(pdev, phys_addr, size);
 	if (!*dma_handle) {
 		printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
 		free_pages((unsigned long)cpuaddr, get_order(size));
@@ -127,11 +126,12 @@
 void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 			  dma_addr_t dma_handle)
 {
-	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
 	BUG_ON(dev->bus != &pci_bus_type);
 
-	pcibr_dma_unmap(pcidev_info, dma_handle, 0);
+	provider->dma_unmap(pdev, dma_handle, 0);
 	free_pages((unsigned long)cpu_addr, get_order(size));
 }
 EXPORT_SYMBOL(sn_dma_free_coherent);
@@ -159,12 +159,13 @@
 {
 	dma_addr_t dma_addr;
 	unsigned long phys_addr;
-	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
 	BUG_ON(dev->bus != &pci_bus_type);
 
 	phys_addr = __pa(cpu_addr);
-	dma_addr = pcibr_dma_map(pcidev_info, phys_addr, size, 0);
+	dma_addr = provider->dma_map(pdev, phys_addr, size);
 	if (!dma_addr) {
 		printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
 		return 0;
@@ -187,10 +188,12 @@
 void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 			 int direction)
 {
-	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
 	BUG_ON(dev->bus != &pci_bus_type);
-	pcibr_dma_unmap(pcidev_info, dma_addr, direction);
+
+	provider->dma_unmap(pdev, dma_addr, direction);
 }
 EXPORT_SYMBOL(sn_dma_unmap_single);
 
@@ -207,12 +210,13 @@
 		     int nhwentries, int direction)
 {
 	int i;
-	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
 	BUG_ON(dev->bus != &pci_bus_type);
 
 	for (i = 0; i < nhwentries; i++, sg++) {
-		pcibr_dma_unmap(pcidev_info, sg->dma_address, direction);
+		provider->dma_unmap(pdev, sg->dma_address, direction);
 		sg->dma_address = (dma_addr_t) NULL;
 		sg->dma_length = 0;
 	}
@@ -233,7 +237,8 @@
 {
 	unsigned long phys_addr;
 	struct scatterlist *saved_sg = sg;
-	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 	int i;
 
 	BUG_ON(dev->bus != &pci_bus_type);
@@ -243,8 +248,8 @@
 	 */
 	for (i = 0; i < nhwentries; i++, sg++) {
 		phys_addr = SG_ENT_PHYS_ADDRESS(sg);
-		sg->dma_address = pcibr_dma_map(pcidev_info, phys_addr,
-						sg->length, 0);
+		sg->dma_address = provider->dma_map(pdev,
+						    phys_addr, sg->length);
 
 		if (!sg->dma_address) {
 			printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
index 9d68546..0e47bce8 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
@@ -8,8 +8,8 @@
 
 #include <linux/types.h>
 #include <asm/sn/sn_sal.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 
 int pcibr_invalidate_ate = 0;	/* by default don't invalidate ATE on free */
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index b1d66ac..64af2b2 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -12,8 +12,8 @@
 #include <asm/sn/geo.h>
 #include "xtalk/xwidgetdev.h"
 #include "xtalk/hubdev.h"
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/tiocp.h"
 #include "pci/pic.h"
 #include "pci/pcibr_provider.h"
@@ -40,7 +40,7 @@
  *      we do not have to allocate entries in the PMU.
  */
 
-static uint64_t
+static dma_addr_t
 pcibr_dmamap_ate32(struct pcidev_info *info,
 		   uint64_t paddr, size_t req_size, uint64_t flags)
 {
@@ -109,7 +109,7 @@
 	return pci_addr;
 }
 
-static uint64_t
+static dma_addr_t
 pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
 			uint64_t dma_attributes)
 {
@@ -141,7 +141,7 @@
 
 }
 
-static uint64_t
+static dma_addr_t
 pcibr_dmatrans_direct32(struct pcidev_info * info,
 			uint64_t paddr, size_t req_size, uint64_t flags)
 {
@@ -180,11 +180,11 @@
  * DMA mappings for Direct 64 and 32 do not have any DMA maps.
  */
 void
-pcibr_dma_unmap(struct pcidev_info *pcidev_info, dma_addr_t dma_handle,
-		int direction)
+pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction)
 {
-	struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
-	    pdi_pcibus_info;
+	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
+	struct pcibus_info *pcibus_info =
+	    (struct pcibus_info *)pcidev_info->pdi_pcibus_info;
 
 	if (IS_PCI32_MAPPED(dma_handle)) {
 		int ate_index;
@@ -301,7 +301,7 @@
 		spin_lock_irqsave(&((struct sn_flush_device_list *)p)->
 				  sfdl_flush_lock, flags);
 
-		p->sfdl_flush_value = 0;
+		*p->sfdl_flush_addr = 0;
 
 		/* force an interrupt. */
 		*(volatile uint32_t *)(p->sfdl_force_int_addr) = 1;
@@ -316,64 +316,63 @@
 }
 
 /*
- * Wrapper DMA interface.  Called from pci_dma.c routines.
+ * DMA interfaces.  Called from pci_dma.c routines.
  */
 
-uint64_t
-pcibr_dma_map(struct pcidev_info * pcidev_info, unsigned long phys_addr,
-	      size_t size, unsigned int flags)
+dma_addr_t
+pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
 {
 	dma_addr_t dma_handle;
-	struct pci_dev *pcidev = pcidev_info->pdi_linux_pcidev;
+	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
 
-	if (flags & SN_PCIDMA_CONSISTENT) {
-		/* sn_pci_alloc_consistent interfaces */
-		if (pcidev->dev.coherent_dma_mask == ~0UL) {
-			dma_handle =
-			    pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-						    PCI64_ATTR_BAR);
-		} else {
-			dma_handle =
-			    (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
-							    phys_addr, size,
-							    PCI32_ATE_BAR);
-		}
+	/* SN cannot support DMA addresses smaller than 32 bits. */
+	if (hwdev->dma_mask < 0x7fffffff) {
+		return 0;
+	}
+
+	if (hwdev->dma_mask == ~0UL) {
+		/*
+		 * Handle the most common case: 64 bit cards.  This
+		 * call should always succeed.
+		 */
+
+		dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
+						     PCI64_ATTR_PREF);
 	} else {
-		/* map_sg/map_single interfaces */
-
-		/* SN cannot support DMA addresses smaller than 32 bits. */
-		if (pcidev->dma_mask < 0x7fffffff) {
-			return 0;
-		}
-
-		if (pcidev->dma_mask == ~0UL) {
+		/* Handle 32-63 bit cards via direct mapping */
+		dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
+						     size, 0);
+		if (!dma_handle) {
 			/*
-			 * Handle the most common case: 64 bit cards.  This
-			 * call should always succeed.
+			 * It is a 32 bit card and we cannot do direct mapping,
+			 * so we use an ATE.
 			 */
 
-			dma_handle =
-			    pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-						    PCI64_ATTR_PREF);
-		} else {
-			/* Handle 32-63 bit cards via direct mapping */
-			dma_handle =
-			    pcibr_dmatrans_direct32(pcidev_info, phys_addr,
-						    size, 0);
-			if (!dma_handle) {
-				/*
-				 * It is a 32 bit card and we cannot do direct mapping,
-				 * so we use an ATE.
-				 */
-
-				dma_handle =
-				    pcibr_dmamap_ate32(pcidev_info, phys_addr,
-						       size, PCI32_ATE_PREF);
-			}
+			dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
+							size, PCI32_ATE_PREF);
 		}
 	}
 
 	return dma_handle;
 }
 
+dma_addr_t
+pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
+			 size_t size)
+{
+	dma_addr_t dma_handle;
+	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
+
+	if (hwdev->dev.coherent_dma_mask == ~0UL) {
+		dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
+					    PCI64_ATTR_BAR);
+	} else {
+		dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
+						    phys_addr, size,
+						    PCI32_ATE_BAR);
+	}
+
+	return dma_handle;
+}
+
 EXPORT_SYMBOL(sn_dma_flush);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 92bd278..3893999 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -13,8 +13,8 @@
 #include "xtalk/xwidgetdev.h"
 #include <asm/sn/geo.h>
 #include "xtalk/hubdev.h"
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 #include <asm/sn/addrs.h>
 
@@ -168,3 +168,23 @@
 		pcibr_force_interrupt(sn_irq_info);
 	}
 }
+
+/*
+ * Provider entries for PIC/CP
+ */
+
+struct sn_pcibus_provider pcibr_provider = {
+	.dma_map = pcibr_dma_map,
+	.dma_map_consistent = pcibr_dma_map_consistent,
+	.dma_unmap = pcibr_dma_unmap,
+	.bus_fixup = pcibr_bus_fixup,
+};
+
+int
+pcibr_init_provider(void)
+{
+	sn_pci_provider[PCIIO_ASIC_TYPE_PIC] = &pcibr_provider;
+	sn_pci_provider[PCIIO_ASIC_TYPE_TIOCP] = &pcibr_provider;
+
+	return 0;
+}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
index 74a74a7..865c11c 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
@@ -8,8 +8,8 @@
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/tiocp.h"
 #include "pci/pic.h"
 #include "pci/pcibr_provider.h"
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
new file mode 100644
index 0000000..8dae9eb
--- /dev/null
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -0,0 +1,668 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/tioca_provider.h>
+
+uint32_t tioca_gart_found;
+EXPORT_SYMBOL(tioca_gart_found);	/* used by agp-sgi */
+
+LIST_HEAD(tioca_list);
+EXPORT_SYMBOL(tioca_list);	/* used by agp-sgi */
+
+static int tioca_gart_init(struct tioca_kernel *);
+
+/**
+ * tioca_gart_init - Initialize SGI TIOCA GART
+ * @tioca_common: ptr to common prom/kernel struct identifying the 
+ *
+ * If the indicated tioca has devices present, initialize its associated
+ * GART MMR's and kernel memory.
+ */
+static int
+tioca_gart_init(struct tioca_kernel *tioca_kern)
+{
+	uint64_t ap_reg;
+	uint64_t offset;
+	struct page *tmp;
+	struct tioca_common *tioca_common;
+	volatile struct tioca *ca_base;
+
+	tioca_common = tioca_kern->ca_common;
+	ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+
+	if (list_empty(tioca_kern->ca_devices))
+		return 0;
+
+	ap_reg = 0;
+
+	/*
+	 * Validate aperature size
+	 */
+
+	switch (CA_APERATURE_SIZE >> 20) {
+	case 4:
+		ap_reg |= (0x3ff << CA_GART_AP_SIZE_SHFT);	/* 4MB */
+		break;
+	case 8:
+		ap_reg |= (0x3fe << CA_GART_AP_SIZE_SHFT);	/* 8MB */
+		break;
+	case 16:
+		ap_reg |= (0x3fc << CA_GART_AP_SIZE_SHFT);	/* 16MB */
+		break;
+	case 32:
+		ap_reg |= (0x3f8 << CA_GART_AP_SIZE_SHFT);	/* 32 MB */
+		break;
+	case 64:
+		ap_reg |= (0x3f0 << CA_GART_AP_SIZE_SHFT);	/* 64 MB */
+		break;
+	case 128:
+		ap_reg |= (0x3e0 << CA_GART_AP_SIZE_SHFT);	/* 128 MB */
+		break;
+	case 256:
+		ap_reg |= (0x3c0 << CA_GART_AP_SIZE_SHFT);	/* 256 MB */
+		break;
+	case 512:
+		ap_reg |= (0x380 << CA_GART_AP_SIZE_SHFT);	/* 512 MB */
+		break;
+	case 1024:
+		ap_reg |= (0x300 << CA_GART_AP_SIZE_SHFT);	/* 1GB */
+		break;
+	case 2048:
+		ap_reg |= (0x200 << CA_GART_AP_SIZE_SHFT);	/* 2GB */
+		break;
+	case 4096:
+		ap_reg |= (0x000 << CA_GART_AP_SIZE_SHFT);	/* 4 GB */
+		break;
+	default:
+		printk(KERN_ERR "%s:  Invalid CA_APERATURE_SIZE "
+		       "0x%lx\n", __FUNCTION__, (ulong) CA_APERATURE_SIZE);
+		return -1;
+	}
+
+	/*
+	 * Set up other aperature parameters
+	 */
+
+	if (PAGE_SIZE >= 16384) {
+		tioca_kern->ca_ap_pagesize = 16384;
+		ap_reg |= CA_GART_PAGE_SIZE;
+	} else {
+		tioca_kern->ca_ap_pagesize = 4096;
+	}
+
+	tioca_kern->ca_ap_size = CA_APERATURE_SIZE;
+	tioca_kern->ca_ap_bus_base = CA_APERATURE_BASE;
+	tioca_kern->ca_gart_entries =
+	    tioca_kern->ca_ap_size / tioca_kern->ca_ap_pagesize;
+
+	ap_reg |= (CA_GART_AP_ENB_AGP | CA_GART_AP_ENB_PCI);
+	ap_reg |= tioca_kern->ca_ap_bus_base;
+
+	/*
+	 * Allocate and set up the GART
+	 */
+
+	tioca_kern->ca_gart_size = tioca_kern->ca_gart_entries * sizeof(u64);
+	tmp =
+	    alloc_pages_node(tioca_kern->ca_closest_node,
+			     GFP_KERNEL | __GFP_ZERO,
+			     get_order(tioca_kern->ca_gart_size));
+
+	if (!tmp) {
+		printk(KERN_ERR "%s:  Could not allocate "
+		       "%lu bytes (order %d) for GART\n",
+		       __FUNCTION__,
+		       tioca_kern->ca_gart_size,
+		       get_order(tioca_kern->ca_gart_size));
+		return -ENOMEM;
+	}
+
+	tioca_kern->ca_gart = page_address(tmp);
+	tioca_kern->ca_gart_coretalk_addr =
+	    PHYS_TO_TIODMA(virt_to_phys(tioca_kern->ca_gart));
+
+	/*
+	 * Compute PCI/AGP convenience fields 
+	 */
+
+	offset = CA_PCI32_MAPPED_BASE - CA_APERATURE_BASE;
+	tioca_kern->ca_pciap_base = CA_PCI32_MAPPED_BASE;
+	tioca_kern->ca_pciap_size = CA_PCI32_MAPPED_SIZE;
+	tioca_kern->ca_pcigart_start = offset / tioca_kern->ca_ap_pagesize;
+	tioca_kern->ca_pcigart_base =
+	    tioca_kern->ca_gart_coretalk_addr + offset;
+	tioca_kern->ca_pcigart =
+	    &tioca_kern->ca_gart[tioca_kern->ca_pcigart_start];
+	tioca_kern->ca_pcigart_entries =
+	    tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;
+	tioca_kern->ca_pcigart_pagemap =
+	    kcalloc(1, tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
+	if (!tioca_kern->ca_pcigart_pagemap) {
+		free_pages((unsigned long)tioca_kern->ca_gart,
+			   get_order(tioca_kern->ca_gart_size));
+		return -1;
+	}
+
+	offset = CA_AGP_MAPPED_BASE - CA_APERATURE_BASE;
+	tioca_kern->ca_gfxap_base = CA_AGP_MAPPED_BASE;
+	tioca_kern->ca_gfxap_size = CA_AGP_MAPPED_SIZE;
+	tioca_kern->ca_gfxgart_start = offset / tioca_kern->ca_ap_pagesize;
+	tioca_kern->ca_gfxgart_base =
+	    tioca_kern->ca_gart_coretalk_addr + offset;
+	tioca_kern->ca_gfxgart =
+	    &tioca_kern->ca_gart[tioca_kern->ca_gfxgart_start];
+	tioca_kern->ca_gfxgart_entries =
+	    tioca_kern->ca_gfxap_size / tioca_kern->ca_ap_pagesize;
+
+	/*
+	 * various control settings:
+	 *      use agp op-combining
+	 *      use GET semantics to fetch memory
+	 *      participate in coherency domain
+	 * 	DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029
+	 */
+
+	ca_base->ca_control1 |= CA_AGPDMA_OP_ENB_COMBDELAY;	/* PV895469 ? */
+	ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
+	ca_base->ca_control2 |= (0x2ull << CA_GART_MEM_PARAM_SHFT);
+	tioca_kern->ca_gart_iscoherent = 1;
+	ca_base->ca_control2 &=
+	    ~(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB);
+
+	/*
+	 * Unmask GART fetch error interrupts.  Clear residual errors first.
+	 */
+
+	ca_base->ca_int_status_alias = CA_GART_FETCH_ERR;
+	ca_base->ca_mult_error_alias = CA_GART_FETCH_ERR;
+	ca_base->ca_int_mask &= ~CA_GART_FETCH_ERR;
+
+	/*
+	 * Program the aperature and gart registers in TIOCA
+	 */
+
+	ca_base->ca_gart_aperature = ap_reg;
+	ca_base->ca_gart_ptr_table = tioca_kern->ca_gart_coretalk_addr | 1;
+
+	return 0;
+}
+
+/**
+ * tioca_fastwrite_enable - enable AGP FW for a tioca and its functions
+ * @tioca_kernel: structure representing the CA
+ *
+ * Given a CA, scan all attached functions making sure they all support
+ * FastWrite.  If so, enable FastWrite for all functions and the CA itself.
+ */
+
+void
+tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
+{
+	int cap_ptr;
+	uint64_t ca_control1;
+	uint32_t reg;
+	struct tioca *tioca_base;
+	struct pci_dev *pdev;
+	struct tioca_common *common;
+
+	common = tioca_kern->ca_common;
+
+	/*
+	 * Scan all vga controllers on this bus making sure they all
+	 * suport FW.  If not, return.
+	 */
+
+	list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
+		if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
+			continue;
+
+		cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+		if (!cap_ptr)
+			return;	/* no AGP CAP means no FW */
+
+		pci_read_config_dword(pdev, cap_ptr + PCI_AGP_STATUS, &reg);
+		if (!(reg & PCI_AGP_STATUS_FW))
+			return;	/* function doesn't support FW */
+	}
+
+	/*
+	 * Set fw for all vga fn's
+	 */
+
+	list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
+		if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
+			continue;
+
+		cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+		pci_read_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, &reg);
+		reg |= PCI_AGP_COMMAND_FW;
+		pci_write_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, reg);
+	}
+
+	/*
+	 * Set ca's fw to match
+	 */
+
+	tioca_base = (struct tioca *)common->ca_common.bs_base;
+	ca_control1 = tioca_base->ca_control1;
+	ca_control1 |= CA_AGP_FW_ENABLE;
+	tioca_base->ca_control1 = ca_control1;
+}
+
+EXPORT_SYMBOL(tioca_fastwrite_enable);	/* used by agp-sgi */
+
+/**
+ * tioca_dma_d64 - create a DMA mapping using 64-bit direct mode
+ * @paddr: system physical address
+ *
+ * Map @paddr into 64-bit CA bus space.  No device context is necessary.
+ * Bits 53:0 come from the coretalk address.  We just need to mask in the
+ * following optional bits of the 64-bit pci address:
+ *
+ * 63:60 - Coretalk Packet Type -  0x1 for Mem Get/Put (coherent)
+ *                                 0x2 for PIO (non-coherent)
+ *                                 We will always use 0x1
+ * 55:55 - Swap bytes		   Currently unused
+ */
+static uint64_t
+tioca_dma_d64(unsigned long paddr)
+{
+	dma_addr_t bus_addr;
+
+	bus_addr = PHYS_TO_TIODMA(paddr);
+
+	BUG_ON(!bus_addr);
+	BUG_ON(bus_addr >> 54);
+
+	/* Set upper nibble to Cache Coherent Memory op */
+	bus_addr |= (1UL << 60);
+
+	return bus_addr;
+}
+
+/**
+ * tioca_dma_d48 - create a DMA mapping using 48-bit direct mode
+ * @pdev: linux pci_dev representing the function
+ * @paddr: system physical address
+ *
+ * Map @paddr into 64-bit bus space of the CA associated with @pcidev_info.
+ *
+ * The CA agp 48 bit direct address falls out as follows:
+ *
+ * When direct mapping AGP addresses, the 48 bit AGP address is
+ * constructed as follows:
+ *
+ * [47:40] - Low 8 bits of the page Node ID extracted from coretalk
+ *              address [47:40].  The upper 8 node bits are fixed
+ *              and come from the xxx register bits [5:0]
+ * [39:38] - Chiplet ID extracted from coretalk address [39:38]
+ * [37:00] - node offset extracted from coretalk address [37:00]
+ * 
+ * Since the node id in general will be non-zero, and the chiplet id
+ * will always be non-zero, it follows that the device must support
+ * a dma mask of at least 0xffffffffff (40 bits) to target node 0
+ * and in general should be 0xffffffffffff (48 bits) to target nodes
+ * up to 255.  Nodes above 255 need the support of the xxx register,
+ * and so a given CA can only directly target nodes in the range
+ * xxx - xxx+255.
+ */
+static uint64_t
+tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
+{
+	struct tioca_common *tioca_common;
+	struct tioca *ca_base;
+	uint64_t ct_addr;
+	dma_addr_t bus_addr;
+	uint32_t node_upper;
+	uint64_t agp_dma_extn;
+	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
+
+	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
+	ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+
+	ct_addr = PHYS_TO_TIODMA(paddr);
+	if (!ct_addr)
+		return 0;
+
+	bus_addr = (dma_addr_t) (ct_addr & 0xffffffffffff);
+	node_upper = ct_addr >> 48;
+
+	if (node_upper > 64) {
+		printk(KERN_ERR "%s:  coretalk addr 0x%p node id out "
+		       "of range\n", __FUNCTION__, (void *)ct_addr);
+		return 0;
+	}
+
+	agp_dma_extn = ca_base->ca_agp_dma_addr_extn;
+	if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
+		printk(KERN_ERR "%s:  coretalk upper node (%u) "
+		       "mismatch with ca_agp_dma_addr_extn (%lu)\n",
+		       __FUNCTION__,
+		       node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT));
+		return 0;
+	}
+
+	return bus_addr;
+}
+
+/**
+ * tioca_dma_mapped - create a DMA mapping using a CA GART 
+ * @pdev: linux pci_dev representing the function
+ * @paddr: host physical address to map
+ * @req_size: len (bytes) to map
+ *
+ * Map @paddr into CA address space using the GART mechanism.  The mapped
+ * dma_addr_t is guarenteed to be contiguous in CA bus space.
+ */
+static dma_addr_t
+tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
+{
+	int i, ps, ps_shift, entry, entries, mapsize, last_entry;
+	uint64_t xio_addr, end_xio_addr;
+	struct tioca_common *tioca_common;
+	struct tioca_kernel *tioca_kern;
+	dma_addr_t bus_addr = 0;
+	struct tioca_dmamap *ca_dmamap;
+	void *map;
+	unsigned long flags;
+	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);;
+
+	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
+	tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
+
+	xio_addr = PHYS_TO_TIODMA(paddr);
+	if (!xio_addr)
+		return 0;
+
+	spin_lock_irqsave(&tioca_kern->ca_lock, flags);
+
+	/*
+	 * allocate a map struct
+	 */
+
+	ca_dmamap = kcalloc(1, sizeof(struct tioca_dmamap), GFP_ATOMIC);
+	if (!ca_dmamap)
+		goto map_return;
+
+	/*
+	 * Locate free entries that can hold req_size.  Account for
+	 * unaligned start/length when allocating.
+	 */
+
+	ps = tioca_kern->ca_ap_pagesize;	/* will be power of 2 */
+	ps_shift = ffs(ps) - 1;
+	end_xio_addr = xio_addr + req_size - 1;
+
+	entries = (end_xio_addr >> ps_shift) - (xio_addr >> ps_shift) + 1;
+
+	map = tioca_kern->ca_pcigart_pagemap;
+	mapsize = tioca_kern->ca_pcigart_entries;
+
+	entry = find_first_zero_bit(map, mapsize);
+	while (entry < mapsize) {
+		last_entry = find_next_bit(map, mapsize, entry);
+
+		if (last_entry - entry >= entries)
+			break;
+
+		entry = find_next_zero_bit(map, mapsize, last_entry);
+	}
+
+	if (entry > mapsize)
+		goto map_return;
+
+	for (i = 0; i < entries; i++)
+		set_bit(entry + i, map);
+
+	bus_addr = tioca_kern->ca_pciap_base + (entry * ps);
+
+	ca_dmamap->cad_dma_addr = bus_addr;
+	ca_dmamap->cad_gart_size = entries;
+	ca_dmamap->cad_gart_entry = entry;
+	list_add(&ca_dmamap->cad_list, &tioca_kern->ca_dmamaps);
+
+	if (xio_addr % ps) {
+		tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
+		bus_addr += xio_addr & (ps - 1);
+		xio_addr &= ~(ps - 1);
+		xio_addr += ps;
+		entry++;
+	}
+
+	while (xio_addr < end_xio_addr) {
+		tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
+		xio_addr += ps;
+		entry++;
+	}
+
+	tioca_tlbflush(tioca_kern);
+
+map_return:
+	spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
+	return bus_addr;
+}
+
+/**
+ * tioca_dma_unmap - release CA mapping resources
+ * @pdev: linux pci_dev representing the function
+ * @bus_addr: bus address returned by an earlier tioca_dma_map
+ * @dir: mapping direction (unused)
+ *
+ * Locate mapping resources associated with @bus_addr and release them.
+ * For mappings created using the direct modes (64 or 48) there are no
+ * resources to release.
+ */
+void
+tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
+{
+	int i, entry;
+	struct tioca_common *tioca_common;
+	struct tioca_kernel *tioca_kern;
+	struct tioca_dmamap *map;
+	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
+	unsigned long flags;
+
+	tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
+	tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
+
+	/* return straight away if this isn't be a mapped address */
+
+	if (bus_addr < tioca_kern->ca_pciap_base ||
+	    bus_addr >= (tioca_kern->ca_pciap_base + tioca_kern->ca_pciap_size))
+		return;
+
+	spin_lock_irqsave(&tioca_kern->ca_lock, flags);
+
+	list_for_each_entry(map, &tioca_kern->ca_dmamaps, cad_list)
+	    if (map->cad_dma_addr == bus_addr)
+		break;
+
+	BUG_ON(map == NULL);
+
+	entry = map->cad_gart_entry;
+
+	for (i = 0; i < map->cad_gart_size; i++, entry++) {
+		clear_bit(entry, tioca_kern->ca_pcigart_pagemap);
+		tioca_kern->ca_pcigart[entry] = 0;
+	}
+	tioca_tlbflush(tioca_kern);
+
+	list_del(&map->cad_list);
+	spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
+	kfree(map);
+}
+
+/**
+ * tioca_dma_map - map pages for PCI DMA
+ * @pdev: linux pci_dev representing the function
+ * @paddr: host physical address to map
+ * @byte_count: bytes to map
+ *
+ * This is the main wrapper for mapping host physical pages to CA PCI space.
+ * The mapping mode used is based on the devices dma_mask.  As a last resort
+ * use the GART mapped mode.
+ */
+uint64_t
+tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
+{
+	uint64_t mapaddr;
+
+	/*
+	 * If card is 64 or 48 bit addresable, use a direct mapping.  32
+	 * bit direct is so restrictive w.r.t. where the memory resides that
+	 * we don't use it even though CA has some support.
+	 */
+
+	if (pdev->dma_mask == ~0UL)
+		mapaddr = tioca_dma_d64(paddr);
+	else if (pdev->dma_mask == 0xffffffffffffUL)
+		mapaddr = tioca_dma_d48(pdev, paddr);
+	else
+		mapaddr = 0;
+
+	/* Last resort ... use PCI portion of CA GART */
+
+	if (mapaddr == 0)
+		mapaddr = tioca_dma_mapped(pdev, paddr, byte_count);
+
+	return mapaddr;
+}
+
+/**
+ * tioca_error_intr_handler - SGI TIO CA error interrupt handler
+ * @irq: unused
+ * @arg: pointer to tioca_common struct for the given CA
+ * @pt: unused
+ *
+ * Handle a CA error interrupt.  Simply a wrapper around a SAL call which
+ * defers processing to the SGI prom.
+ */
+static irqreturn_t
+tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
+{
+	struct tioca_common *soft = arg;
+	struct ia64_sal_retval ret_stuff;
+	uint64_t segment;
+	uint64_t busnum;
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+
+	segment = 0;
+	busnum = soft->ca_common.bs_persist_busnum;
+
+	SAL_CALL_NOLOCK(ret_stuff,
+			(u64) SN_SAL_IOIF_ERROR_INTERRUPT,
+			segment, busnum, 0, 0, 0, 0, 0);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * tioca_bus_fixup - perform final PCI fixup for a TIO CA bus
+ * @prom_bussoft: Common prom/kernel struct representing the bus
+ *
+ * Replicates the tioca_common pointed to by @prom_bussoft in kernel
+ * space.  Allocates and initializes a kernel-only area for a given CA,
+ * and sets up an irq for handling CA error interrupts.
+ *
+ * On successful setup, returns the kernel version of tioca_common back to
+ * the caller.
+ */
+void *
+tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft)
+{
+	struct tioca_common *tioca_common;
+	struct tioca_kernel *tioca_kern;
+	struct pci_bus *bus;
+
+	/* sanity check prom rev */
+
+	if (sn_sal_rev_major() < 4 ||
+	    (sn_sal_rev_major() == 4 && sn_sal_rev_minor() < 6)) {
+		printk
+		    (KERN_ERR "%s:  SGI prom rev 4.06 or greater required "
+		     "for tioca support\n", __FUNCTION__);
+		return NULL;
+	}
+
+	/*
+	 * Allocate kernel bus soft and copy from prom.
+	 */
+
+	tioca_common = kcalloc(1, sizeof(struct tioca_common), GFP_KERNEL);
+	if (!tioca_common)
+		return NULL;
+
+	memcpy(tioca_common, prom_bussoft, sizeof(struct tioca_common));
+	tioca_common->ca_common.bs_base |= __IA64_UNCACHED_OFFSET;
+
+	/* init kernel-private area */
+
+	tioca_kern = kcalloc(1, sizeof(struct tioca_kernel), GFP_KERNEL);
+	if (!tioca_kern) {
+		kfree(tioca_common);
+		return NULL;
+	}
+
+	tioca_kern->ca_common = tioca_common;
+	spin_lock_init(&tioca_kern->ca_lock);
+	INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
+	tioca_kern->ca_closest_node =
+	    nasid_to_cnodeid(tioca_common->ca_closest_nasid);
+	tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
+
+	bus = pci_find_bus(0, tioca_common->ca_common.bs_persist_busnum);
+	BUG_ON(!bus);
+	tioca_kern->ca_devices = &bus->devices;
+
+	/* init GART */
+
+	if (tioca_gart_init(tioca_kern) < 0) {
+		kfree(tioca_kern);
+		kfree(tioca_common);
+		return NULL;
+	}
+
+	tioca_gart_found++;
+	list_add(&tioca_kern->ca_list, &tioca_list);
+
+	if (request_irq(SGI_TIOCA_ERROR,
+			tioca_error_intr_handler,
+			SA_SHIRQ, "TIOCA error", (void *)tioca_common))
+		printk(KERN_WARNING
+		       "%s:  Unable to get irq %d.  "
+		       "Error interrupts won't be routed for TIOCA bus %d\n",
+		       __FUNCTION__, SGI_TIOCA_ERROR,
+		       (int)tioca_common->ca_common.bs_persist_busnum);
+
+	return tioca_common;
+}
+
+static struct sn_pcibus_provider tioca_pci_interfaces = {
+	.dma_map = tioca_dma_map,
+	.dma_map_consistent = tioca_dma_map,
+	.dma_unmap = tioca_dma_unmap,
+	.bus_fixup = tioca_bus_fixup,
+};
+
+/**
+ * tioca_init_provider - init SN PCI provider ops for TIO CA
+ */
+int
+tioca_init_provider(void)
+{
+	sn_pci_provider[PCIIO_ASIC_TYPE_TIOCA] = &tioca_pci_interfaces;
+	return 0;
+}
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 8b40f36..124f7c1 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/string.h>
+#include <linux/signal.h>
 
 #include <asm/cacheflush.h>
 #include <asm/io.h>
@@ -665,7 +666,7 @@
 	case PTRACE_SYSCALL:
 	case PTRACE_CONT:
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -700,7 +701,7 @@
 		unsigned long pc, insn;
 
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		if ((child->ptrace & PT_DTRACE) == 0) {
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 0beb533..f4e1e5e 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/config.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -251,7 +252,7 @@
 			long tmp;
 
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			if (request == PTRACE_SYSCALL) {
 					child->thread.work.syscall_trace = ~0;
@@ -292,7 +293,7 @@
 			long tmp;
 
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			child->thread.work.syscall_trace = 0;
 			tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index fc4615b..e729bd2 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -534,6 +534,11 @@
 
 endmenu
 
+config ISA_DMA_API
+	bool
+	depends on !M5272
+	default y
+
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config PCI
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 15cf790..9724e1c 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/config.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -240,7 +241,7 @@
 			long tmp;
 
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			if (request == PTRACE_SYSCALL)
 				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -278,7 +279,7 @@
 			long tmp;
 
 			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
+			if (!valid_signal(data))
 				break;
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 5e666aa..ab99446 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1656,3 +1656,7 @@
 config GENERIC_IRQ_PROBE
 	bool
 	default y
+
+config ISA_DMA_API
+	bool
+	default y
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 92f2c39..92e70ca 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -26,6 +26,7 @@
 #include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/cpu.h>
 #include <asm/fpu.h>
@@ -257,7 +258,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL) {
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -300,25 +301,38 @@
 	return ret;
 }
 
+static inline int audit_arch(void)
+{
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#ifdef CONFIG_MIPS64
+	if (!(current->thread.mflags & MF_32BIT_REGS))
+		return AUDIT_ARCH_MIPSEL64;
+#endif /* MIPS64 */
+	return AUDIT_ARCH_MIPSEL;
+
+#else /* big endian... */
+#ifdef CONFIG_MIPS64
+	if (!(current->thread.mflags & MF_32BIT_REGS))
+		return AUDIT_ARCH_MIPS64;
+#endif /* MIPS64 */
+	return AUDIT_ARCH_MIPS;
+
+#endif /* endian */
+}
+
 /*
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
 asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if (unlikely(current->audit_context)) {
-		if (!entryexit)
-			audit_syscall_entry(current, regs->regs[2],
-			                    regs->regs[4], regs->regs[5],
-			                    regs->regs[6], regs->regs[7]);
-		else
-			audit_syscall_exit(current, regs->regs[2]);
-	}
+	if (unlikely(current->audit_context) && entryexit)
+		audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]), regs->regs[2]);
 
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
+		goto out;
 	if (!(current->ptrace & PT_PTRACED))
-		return;
+		goto out;
 
 	/* The 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
@@ -334,4 +348,9 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
+ out:
+	if (unlikely(current->audit_context) && !entryexit)
+		audit_syscall_entry(current, audit_arch(), regs->regs[2],
+				    regs->regs[4], regs->regs[5],
+				    regs->regs[6], regs->regs[7]);
 }
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 611dee9..eee2079 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -24,6 +24,7 @@
 #include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/cpu.h>
 #include <asm/fpu.h>
@@ -241,7 +242,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned int) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL) {
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 598bfe7..ae2a131 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -374,22 +374,6 @@
 }
 
 /*
- * Native ABI that is O32 or N64 version
- */
-asmlinkage long sys_shmat(int shmid, char __user *shmaddr,
-                          int shmflg, unsigned long *addr)
-{
-	unsigned long raddr;
-	int err;
-
-	err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-	if (err)
-		return err;
-
-	return put_user(raddr, addr);
-}
-
-/*
  * No implemented yet ...
  */
 asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 5b5cd00..e7e7c56 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -45,6 +45,10 @@
 config PM
 	bool
 
+config ISA_DMA_API
+	bool
+	default y
+
 source "init/Kconfig"
 
 
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 2937a92..c07db9d 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -17,6 +17,7 @@
 #include <linux/personality.h>
 #include <linux/security.h>
 #include <linux/compat.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -285,7 +286,7 @@
 		ret = -EIO;
 		DBG("sys_ptrace(%s)\n",
 			request == PTRACE_SYSCALL ? "SYSCALL" : "CONT");
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			goto out_tsk;
 		child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
 		if (request == PTRACE_SYSCALL) {
@@ -311,7 +312,7 @@
 	case PTRACE_SINGLEBLOCK:
 		DBG("sys_ptrace(SINGLEBLOCK)\n");
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			goto out_tsk;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		child->ptrace &= ~PT_SINGLESTEP;
@@ -328,7 +329,7 @@
 	case PTRACE_SINGLESTEP:
 		DBG("sys_ptrace(SINGLESTEP)\n");
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			goto out_tsk;
 
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 7958cd8..d15a1d5 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -161,17 +161,6 @@
 	}
 }
 
-long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag)
-{
-	unsigned long raddr;
-	int r;
-
-	r = do_shmat(shmid, shmaddr, shmflag, &raddr);
-	if (r < 0)
-		return r;
-	return raddr;
-}
-
 /* Fucking broken ABI */
 
 #ifdef CONFIG_64BIT
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 779b537..dcfa4d3 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -297,7 +297,7 @@
 	ENTRY_DIFF(msgrcv)
 	ENTRY_SAME(msgget)		/* 190 */
 	ENTRY_SAME(msgctl)
-	ENTRY_SAME(shmat_wrapper)
+	ENTRY_SAME(shmat)
 	ENTRY_SAME(shmdt)
 	ENTRY_SAME(shmget)
 	ENTRY_SAME(shmctl)		/* 195 */
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 74aa1e9..600f23d 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -43,6 +43,10 @@
 	bool
 	default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+	bool
+	default y
+
 source "init/Kconfig"
 
 menu "Processor"
@@ -53,6 +57,7 @@
 
 config 6xx
 	bool "6xx/7xx/74xx/52xx/82xx/83xx"
+	select PPC_FPU
 	help
 	  There are four types of PowerPC chips supported.  The more common
 	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
@@ -72,9 +77,11 @@
 	bool "44x"
 
 config POWER3
+	select PPC_FPU
 	bool "POWER3"
 
 config POWER4
+	select PPC_FPU
 	bool "POWER4 and 970 (G5)"
 
 config 8xx
@@ -86,6 +93,9 @@
 
 endchoice
 
+config PPC_FPU
+	bool
+
 config BOOKE
 	bool
 	depends on E500
@@ -1075,6 +1085,10 @@
 
 endmenu
 
+config ISA_DMA_API
+	bool
+	default y
+
 menu "Bus options"
 
 config ISA
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 73cbdda..0432a25 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -53,6 +53,7 @@
 
 head-$(CONFIG_6xx)		+= arch/ppc/kernel/idle_6xx.o
 head-$(CONFIG_POWER4)		+= arch/ppc/kernel/idle_power4.o
+head-$(CONFIG_PPC_FPU)		+= arch/ppc/kernel/fpu.o
 
 core-y				+= arch/ppc/kernel/ arch/ppc/platforms/ \
 				   arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
index 774de8e..f850fb0 100644
--- a/arch/ppc/boot/images/Makefile
+++ b/arch/ppc/boot/images/Makefile
@@ -20,8 +20,9 @@
 
 targets += uImage
 $(obj)/uImage: $(obj)/vmlinux.gz
+	$(Q)rm -f $@
 	$(call if_changed,uimage)
-	@echo '  Image $@ is ready'
+	@echo '  Image: $@' $(if $(wildcard $@),'is ready','not made')
 
 # Files generated that shall be removed upon make clean
 clean-files	:= sImage vmapus vmlinux* miboot* zImage* uImage
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 86bc878..b284451 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -9,6 +9,7 @@
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-$(CONFIG_POWER4)		+= idle_power4.o
+extra-$(CONFIG_PPC_FPU)		+= fpu.o
 extra-y				+= vmlinux.lds
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 79c9294..ff81da9 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -290,6 +290,10 @@
 			/* lwm, stmw */
 			nb = (32 - reg) * 4;
 		}
+
+		if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb+nb0))
+			return -EFAULT;	/* bad address */
+
 		rptr = (unsigned char *) &regs->gpr[reg];
 		if (flags & LD) {
 			for (i = 0; i < nb; ++i)
@@ -368,16 +372,24 @@
 
 	/* Single-precision FP load and store require conversions... */
 	case LD+F+S:
+#ifdef CONFIG_PPC_FPU
 		preempt_disable();
 		enable_kernel_fp();
 		cvt_fd(&data.f, &data.d, &current->thread.fpscr);
 		preempt_enable();
+#else
+		return 0;
+#endif
 		break;
 	case ST+F+S:
+#ifdef CONFIG_PPC_FPU
 		preempt_disable();
 		enable_kernel_fp();
 		cvt_df(&data.d, &data.f, &current->thread.fpscr);
 		preempt_enable();
+#else
+		return 0;
+#endif
 		break;
 	}
 
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
index 74f781b..468721d 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -30,12 +30,14 @@
 	blr
 _GLOBAL(__setup_cpu_750)
 	mflr	r4
+	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	mtlr	r4
 	blr
 _GLOBAL(__setup_cpu_750cx)
 	mflr	r4
+	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	bl	setup_750cx
@@ -43,6 +45,7 @@
 	blr
 _GLOBAL(__setup_cpu_750fx)
 	mflr	r4
+	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	bl	setup_750fx
@@ -50,6 +53,7 @@
 	blr
 _GLOBAL(__setup_cpu_7400)
 	mflr	r4
+	bl	__init_fpu_registers
 	bl	setup_7400_workarounds
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
@@ -57,6 +61,7 @@
 	blr
 _GLOBAL(__setup_cpu_7410)
 	mflr	r4
+	bl	__init_fpu_registers
 	bl	setup_7410_workarounds
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
@@ -80,7 +85,7 @@
 	bne	1f			/* don't invalidate the D-cache */
 	ori	r8,r8,HID0_DCI		/* unless it wasn't enabled */
 1:	sync
-	mtspr	SPRN_HID0,r8			/* enable and invalidate caches */
+	mtspr	SPRN_HID0,r8		/* enable and invalidate caches */
 	sync
 	mtspr	SPRN_HID0,r11		/* enable caches */
 	sync
@@ -152,9 +157,13 @@
 setup_750_7400_hid0:
 	mfspr	r11,SPRN_HID0
 	ori	r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
+	oris	r11,r11,HID0_DPM@h
 BEGIN_FTR_SECTION
-	oris	r11,r11,HID0_DPM@h	/* enable dynamic power mgmt */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+	xori	r11,r11,HID0_BTIC
+END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
+BEGIN_FTR_SECTION
+	xoris	r11,r11,HID0_DPM@h	/* disable dynamic power mgmt */
+END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM)
 	li	r3,HID0_SPD
 	andc	r11,r11,r3		/* clear SPD: enable speculative */
  	li	r3,0
@@ -218,13 +227,15 @@
 
 	/* All of the bits we have to set.....
 	 */
-	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC
+	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE
+	ori	r11,r11,HID0_LRSTK | HID0_BTIC
+	oris	r11,r11,HID0_DPM@h
 BEGIN_FTR_SECTION
 	xori	r11,r11,HID0_BTIC
 END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
 BEGIN_FTR_SECTION
-	oris	r11,r11,HID0_DPM@h	/* enable dynamic power mgmt */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+	xoris	r11,r11,HID0_DPM@h	/* disable dynamic power mgmt */
+END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM)
 
 	/* All of the bits we have to clear....
 	 */
@@ -248,6 +259,25 @@
 	isync
 	blr
 
+/*
+ * Initialize the FPU registers. This is needed to work around an errata
+ * in some 750 cpus where using a not yet initialized FPU register after
+ * power on reset may hang the CPU
+ */
+_GLOBAL(__init_fpu_registers)
+	mfmsr	r10
+	ori	r11,r10,MSR_FP
+	mtmsr	r11
+	isync
+	addis	r9,r3,empty_zero_page@ha
+	addi	r9,r9,empty_zero_page@l
+	REST_32FPRS(0,r9)
+	sync
+	mtmsr	r10
+	isync
+	blr
+
+
 /* Definitions for the table use to save CPU states */
 #define CS_HID0		0
 #define CS_HID1		4
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 035217d..5f075db 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -563,6 +563,65 @@
 	addi	r1,r1,INT_FRAME_SIZE
 	blr
 
+	.globl	fast_exception_return
+fast_exception_return:
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
+	andi.	r10,r9,MSR_RI		/* check for recoverable interrupt */
+	beq	1f			/* if not, we've got problems */
+#endif
+
+2:	REST_4GPRS(3, r11)
+	lwz	r10,_CCR(r11)
+	REST_GPR(1, r11)
+	mtcr	r10
+	lwz	r10,_LINK(r11)
+	mtlr	r10
+	REST_GPR(10, r11)
+	mtspr	SPRN_SRR1,r9
+	mtspr	SPRN_SRR0,r12
+	REST_GPR(9, r11)
+	REST_GPR(12, r11)
+	lwz	r11,GPR11(r11)
+	SYNC
+	RFI
+
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
+/* check if the exception happened in a restartable section */
+1:	lis	r3,exc_exit_restart_end@ha
+	addi	r3,r3,exc_exit_restart_end@l
+	cmplw	r12,r3
+	bge	3f
+	lis	r4,exc_exit_restart@ha
+	addi	r4,r4,exc_exit_restart@l
+	cmplw	r12,r4
+	blt	3f
+	lis	r3,fee_restarts@ha
+	tophys(r3,r3)
+	lwz	r5,fee_restarts@l(r3)
+	addi	r5,r5,1
+	stw	r5,fee_restarts@l(r3)
+	mr	r12,r4		/* restart at exc_exit_restart */
+	b	2b
+
+	.comm	fee_restarts,4
+
+/* aargh, a nonrecoverable interrupt, panic */
+/* aargh, we don't know which trap this is */
+/* but the 601 doesn't implement the RI bit, so assume it's OK */
+3:
+BEGIN_FTR_SECTION
+	b	2b
+END_FTR_SECTION_IFSET(CPU_FTR_601)
+	li	r10,-1
+	stw	r10,TRAP(r11)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	lis	r10,MSR_KERNEL@h
+	ori	r10,r10,MSR_KERNEL@l
+	bl	transfer_to_handler_full
+	.long	nonrecoverable_exception
+	.long	ret_from_except
+#endif
+
 	.globl	sigreturn_exit
 sigreturn_exit:
 	subi	r1,r3,STACK_FRAME_OVERHEAD
diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S
new file mode 100644
index 0000000..6189b26
--- /dev/null
+++ b/arch/ppc/kernel/fpu.S
@@ -0,0 +1,133 @@
+/*
+ *  FPU support code, moved here from head.S so that it can be used
+ *  by chips which use other head-whatever.S files.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/*
+ * This task wants to use the FPU now.
+ * On UP, disable FP for the task which had the FPU previously,
+ * and save its floating-point registers in its thread_struct.
+ * Load up this task's FP registers from its thread_struct,
+ * enable the FPU for the current task and return to the task.
+ */
+	.globl	load_up_fpu
+load_up_fpu:
+	mfmsr	r5
+	ori	r5,r5,MSR_FP
+#ifdef CONFIG_PPC64BRIDGE
+	clrldi	r5,r5,1			/* turn off 64-bit mode */
+#endif /* CONFIG_PPC64BRIDGE */
+	SYNC
+	MTMSRD(r5)			/* enable use of fpu now */
+	isync
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another.  Instead we call giveup_fpu in switch_to.
+ */
+#ifndef CONFIG_SMP
+	tophys(r6,0)			/* get __pa constant */
+	addis	r3,r6,last_task_used_math@ha
+	lwz	r4,last_task_used_math@l(r3)
+	cmpwi	0,r4,0
+	beq	1f
+	add	r4,r4,r6
+	addi	r4,r4,THREAD		/* want last_task_used_math->thread */
+	SAVE_32FPRS(0, r4)
+	mffs	fr0
+	stfd	fr0,THREAD_FPSCR-4(r4)
+	lwz	r5,PT_REGS(r4)
+	add	r5,r5,r6
+	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	li	r10,MSR_FP|MSR_FE0|MSR_FE1
+	andc	r4,r4,r10		/* disable FP for previous task */
+	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+	/* enable use of FP after return */
+	mfspr	r5,SPRN_SPRG3		/* current task's THREAD (phys) */
+	lwz	r4,THREAD_FPEXC_MODE(r5)
+	ori	r9,r9,MSR_FP		/* enable FP for current */
+	or	r9,r9,r4
+	lfd	fr0,THREAD_FPSCR-4(r5)
+	mtfsf	0xff,fr0
+	REST_32FPRS(0, r5)
+#ifndef CONFIG_SMP
+	subi	r4,r5,THREAD
+	sub	r4,r4,r6
+	stw	r4,last_task_used_math@l(r3)
+#endif /* CONFIG_SMP */
+	/* restore registers and return */
+	/* we haven't used ctr or xer or lr */
+	b	fast_exception_return
+
+/*
+ * FP unavailable trap from kernel - print a message, but let
+ * the task use FP in the kernel until it returns to user mode.
+ */
+ 	.globl	KernelFP
+KernelFP:
+	lwz	r3,_MSR(r1)
+	ori	r3,r3,MSR_FP
+	stw	r3,_MSR(r1)		/* enable use of FP after return */
+	lis	r3,86f@h
+	ori	r3,r3,86f@l
+	mr	r4,r2			/* current */
+	lwz	r5,_NIP(r1)
+	bl	printk
+	b	ret_from_except
+86:	.string	"floating point used in kernel (task=%p, pc=%x)\n"
+	.align	4,0
+
+/*
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ */
+	.globl	giveup_fpu
+giveup_fpu:
+	mfmsr	r5
+	ori	r5,r5,MSR_FP
+	SYNC_601
+	ISYNC_601
+	MTMSRD(r5)			/* enable use of fpu now */
+	SYNC_601
+	isync
+	cmpwi	0,r3,0
+	beqlr-				/* if no previous owner, done */
+	addi	r3,r3,THREAD	        /* want THREAD of task */
+	lwz	r5,PT_REGS(r3)
+	cmpwi	0,r5,0
+	SAVE_32FPRS(0, r3)
+	mffs	fr0
+	stfd	fr0,THREAD_FPSCR-4(r3)
+	beq	1f
+	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+	li	r3,MSR_FP|MSR_FE0|MSR_FE1
+	andc	r4,r4,r3		/* disable FP for previous task */
+	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+	li	r5,0
+	lis	r4,last_task_used_math@ha
+	stw	r5,last_task_used_math@l(r4)
+#endif /* CONFIG_SMP */
+	blr
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 1a89a71..a931d77 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -775,133 +775,6 @@
 	EXC_XFER_STD(0x480, UnknownException)
 #endif /* CONFIG_PPC64BRIDGE */
 
-/*
- * This task wants to use the FPU now.
- * On UP, disable FP for the task which had the FPU previously,
- * and save its floating-point registers in its thread_struct.
- * Load up this task's FP registers from its thread_struct,
- * enable the FPU for the current task and return to the task.
- */
-load_up_fpu:
-	mfmsr	r5
-	ori	r5,r5,MSR_FP
-#ifdef CONFIG_PPC64BRIDGE
-	clrldi	r5,r5,1			/* turn off 64-bit mode */
-#endif /* CONFIG_PPC64BRIDGE */
-	SYNC
-	MTMSRD(r5)			/* enable use of fpu now */
-	isync
-/*
- * For SMP, we don't do lazy FPU switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another.  Instead we call giveup_fpu in switch_to.
- */
-#ifndef CONFIG_SMP
-	tophys(r6,0)			/* get __pa constant */
-	addis	r3,r6,last_task_used_math@ha
-	lwz	r4,last_task_used_math@l(r3)
-	cmpwi	0,r4,0
-	beq	1f
-	add	r4,r4,r6
-	addi	r4,r4,THREAD		/* want last_task_used_math->thread */
-	SAVE_32FPRS(0, r4)
-	mffs	fr0
-	stfd	fr0,THREAD_FPSCR-4(r4)
-	lwz	r5,PT_REGS(r4)
-	add	r5,r5,r6
-	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	li	r10,MSR_FP|MSR_FE0|MSR_FE1
-	andc	r4,r4,r10		/* disable FP for previous task */
-	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
-	/* enable use of FP after return */
-	mfspr	r5,SPRN_SPRG3		/* current task's THREAD (phys) */
-	lwz	r4,THREAD_FPEXC_MODE(r5)
-	ori	r9,r9,MSR_FP		/* enable FP for current */
-	or	r9,r9,r4
-	lfd	fr0,THREAD_FPSCR-4(r5)
-	mtfsf	0xff,fr0
-	REST_32FPRS(0, r5)
-#ifndef CONFIG_SMP
-	subi	r4,r5,THREAD
-	sub	r4,r4,r6
-	stw	r4,last_task_used_math@l(r3)
-#endif /* CONFIG_SMP */
-	/* restore registers and return */
-	/* we haven't used ctr or xer or lr */
-	/* fall through to fast_exception_return */
-
-	.globl	fast_exception_return
-fast_exception_return:
-	andi.	r10,r9,MSR_RI		/* check for recoverable interrupt */
-	beq	1f			/* if not, we've got problems */
-2:	REST_4GPRS(3, r11)
-	lwz	r10,_CCR(r11)
-	REST_GPR(1, r11)
-	mtcr	r10
-	lwz	r10,_LINK(r11)
-	mtlr	r10
-	REST_GPR(10, r11)
-	mtspr	SPRN_SRR1,r9
-	mtspr	SPRN_SRR0,r12
-	REST_GPR(9, r11)
-	REST_GPR(12, r11)
-	lwz	r11,GPR11(r11)
-	SYNC
-	RFI
-
-/* check if the exception happened in a restartable section */
-1:	lis	r3,exc_exit_restart_end@ha
-	addi	r3,r3,exc_exit_restart_end@l
-	cmplw	r12,r3
-	bge	3f
-	lis	r4,exc_exit_restart@ha
-	addi	r4,r4,exc_exit_restart@l
-	cmplw	r12,r4
-	blt	3f
-	lis	r3,fee_restarts@ha
-	tophys(r3,r3)
-	lwz	r5,fee_restarts@l(r3)
-	addi	r5,r5,1
-	stw	r5,fee_restarts@l(r3)
-	mr	r12,r4		/* restart at exc_exit_restart */
-	b	2b
-
-	.comm	fee_restarts,4
-
-/* aargh, a nonrecoverable interrupt, panic */
-/* aargh, we don't know which trap this is */
-/* but the 601 doesn't implement the RI bit, so assume it's OK */
-3:
-BEGIN_FTR_SECTION
-	b	2b
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-	li	r10,-1
-	stw	r10,TRAP(r11)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r10,MSR_KERNEL
-	bl	transfer_to_handler_full
-	.long	nonrecoverable_exception
-	.long	ret_from_except
-
-/*
- * FP unavailable trap from kernel - print a message, but let
- * the task use FP in the kernel until it returns to user mode.
- */
-KernelFP:
-	lwz	r3,_MSR(r1)
-	ori	r3,r3,MSR_FP
-	stw	r3,_MSR(r1)		/* enable use of FP after return */
-	lis	r3,86f@h
-	ori	r3,r3,86f@l
-	mr	r4,r2			/* current */
-	lwz	r5,_NIP(r1)
-	bl	printk
-	b	ret_from_except
-86:	.string	"floating point used in kernel (task=%p, pc=%x)\n"
-	.align	4,0
-
 #ifdef CONFIG_ALTIVEC
 /* Note that the AltiVec support is closely modeled after the FP
  * support.  Changes to one are likely to be applicable to the
@@ -1016,42 +889,6 @@
 #endif /* CONFIG_ALTIVEC */
 
 /*
- * giveup_fpu(tsk)
- * Disable FP for the task given as the argument,
- * and save the floating-point registers in its thread_struct.
- * Enables the FPU for use in the kernel on return.
- */
-	.globl	giveup_fpu
-giveup_fpu:
-	mfmsr	r5
-	ori	r5,r5,MSR_FP
-	SYNC_601
-	ISYNC_601
-	MTMSRD(r5)			/* enable use of fpu now */
-	SYNC_601
-	isync
-	cmpwi	0,r3,0
-	beqlr-				/* if no previous owner, done */
-	addi	r3,r3,THREAD	        /* want THREAD of task */
-	lwz	r5,PT_REGS(r3)
-	cmpwi	0,r5,0
-	SAVE_32FPRS(0, r3)
-	mffs	fr0
-	stfd	fr0,THREAD_FPSCR-4(r3)
-	beq	1f
-	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	li	r3,MSR_FP|MSR_FE0|MSR_FE1
-	andc	r4,r4,r3		/* disable FP for previous task */
-	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
-	li	r5,0
-	lis	r4,last_task_used_math@ha
-	stw	r5,last_task_used_math@l(r4)
-#endif /* CONFIG_SMP */
-	blr
-
-/*
  * This code is jumped to from the startup code to copy
  * the kernel image to physical address 0.
  */
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 9ed8165..9b6a8e5 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -426,7 +426,11 @@
 	PROGRAM_EXCEPTION
 
 	/* Floating Point Unavailable Interrupt */
+#ifdef CONFIG_PPC_FPU
+	FP_UNAVAILABLE_EXCEPTION
+#else
 	EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
+#endif
 
 	/* System Call Interrupt */
 	START_EXCEPTION(SystemCall)
@@ -686,8 +690,10 @@
  *
  * The 44x core does not have an FPU.
  */
+#ifndef CONFIG_PPC_FPU
 _GLOBAL(giveup_fpu)
 	blr
+#endif
 
 /*
  * extern void abort(void)
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index 884dac9..f213d12 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -337,4 +337,11 @@
 	addi    r3,r1,STACK_FRAME_OVERHEAD;				      \
 	EXC_XFER_LITE(0x0900, timer_interrupt)
 
+#define FP_UNAVAILABLE_EXCEPTION					      \
+	START_EXCEPTION(FloatingPointUnavailable)			      \
+	NORMAL_EXCEPTION_PROLOG;					      \
+	bne	load_up_fpu;		/* if from user, just load it up */   \
+	addi	r3,r1,STACK_FRAME_OVERHEAD;				      \
+	EXC_XFER_EE_LITE(0x800, KernelFP)
+
 #endif /* __HEAD_BOOKE_H__ */
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index d64bf61..f22ddce 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -504,7 +504,11 @@
 	PROGRAM_EXCEPTION
 
 	/* Floating Point Unavailable Interrupt */
+#ifdef CONFIG_PPC_FPU
+	FP_UNAVAILABLE_EXCEPTION
+#else
 	EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
+#endif
 
 	/* System Call Interrupt */
 	START_EXCEPTION(SystemCall)
@@ -916,10 +920,12 @@
 /*
  * extern void giveup_fpu(struct task_struct *prev)
  *
- * The e500 core does not have an FPU.
+ * Not all FSL Book-E cores have an FPU
  */
+#ifndef CONFIG_PPC_FPU
 _GLOBAL(giveup_fpu)
 	blr
+#endif
 
 /*
  * extern void abort(void)
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 73f7c23..e4f1615 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -1096,17 +1096,7 @@
  * and exceptions as if the cpu had performed the load or store.
  */
 
-#if defined(CONFIG_4xx) || defined(CONFIG_E500)
-_GLOBAL(cvt_fd)
-	lfs	0,0(r3)
-	stfd	0,0(r4)
-	blr
-
-_GLOBAL(cvt_df)
-	lfd	0,0(r3)
-	stfs	0,0(r4)
-	blr
-#else
+#ifdef CONFIG_PPC_FPU
 _GLOBAL(cvt_fd)
 	lfd	0,-4(r5)	/* load up fpscr value */
 	mtfsf	0xff,0
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 98f94b6..47a1530 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1432,7 +1432,7 @@
 	return NULL;
 }
 
-void*
+void __iomem *
 pci_bus_io_base(unsigned int bus)
 {
 	struct pci_controller *hose;
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
index 426b6f7..59d59a8 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/ppc/kernel/ptrace.c
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -356,7 +357,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL) {
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -389,7 +390,7 @@
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		set_single_step(child);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index e97ce63..5dfb42f 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -221,27 +221,26 @@
 			return err;
 	}
 
-	switch (PVR_VER(pvr)) {
-	case 0x0020:	/* 403 family */
-		maj = PVR_MAJ(pvr) + 1;
-		min = PVR_MIN(pvr);
-		break;
-	case 0x1008:	/* 740P/750P ?? */
-		maj = ((pvr >> 8) & 0xFF) - 1;
-		min = pvr & 0xFF;
-		break;
-	case 0x8083:	/* e300 */
+	/* If we are a Freescale core do a simple check so
+	 * we dont have to keep adding cases in the future */
+	if ((PVR_VER(pvr) & 0x8000) == 0x8000) {
 		maj = PVR_MAJ(pvr);
 		min = PVR_MIN(pvr);
-		break;
-	case 0x8020:	/* e500 */
-		maj = PVR_MAJ(pvr);
-		min = PVR_MIN(pvr);
-		break;
-	default:
-		maj = (pvr >> 8) & 0xFF;
-		min = pvr & 0xFF;
-		break;
+	} else {
+		switch (PVR_VER(pvr)) {
+			case 0x0020:	/* 403 family */
+				maj = PVR_MAJ(pvr) + 1;
+				min = PVR_MIN(pvr);
+				break;
+			case 0x1008:	/* 740P/750P ?? */
+				maj = ((pvr >> 8) & 0xFF) - 1;
+				min = pvr & 0xFF;
+				break;
+			default:
+				maj = (pvr >> 8) & 0xFF;
+				min = pvr & 0xFF;
+				break;
+		}
 	}
 
 	seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 645eae1..7c8437da 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -511,7 +511,7 @@
 }
 
 int sys_debug_setcontext(struct ucontext __user *ctx,
-			 int ndbg, struct sig_dbg_op *dbg,
+			 int ndbg, struct sig_dbg_op __user *dbg,
 			 int r6, int r7, int r8,
 			 struct pt_regs *regs)
 {
@@ -632,7 +632,7 @@
 	if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
 	    || __put_user(oldset->sig[0], &sc->oldmask)
 	    || __put_user(oldset->sig[1], &sc->_unused[3])
-	    || __put_user((struct pt_regs *)frame, &sc->regs)
+	    || __put_user((struct pt_regs __user *)frame, &sc->regs)
 	    || __put_user(sig, &sc->signal))
 		goto badframe;
 
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 002322a..f8e7e32 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -176,7 +176,7 @@
 #else
 #define get_mc_reason(regs)	(mfspr(SPRN_MCSR))
 #endif
-#define REASON_FP		0
+#define REASON_FP		ESR_FP
 #define REASON_ILLEGAL		ESR_PIL
 #define REASON_PRIVILEGED	ESR_PPR
 #define REASON_TRAP		ESR_PTR
@@ -403,7 +403,7 @@
 	u8 rA = (instword >> 16) & 0x1f;
 	u8 NB_RB = (instword >> 11) & 0x1f;
 	u32 num_bytes;
-	u32 EA;
+	unsigned long EA;
 	int pos = 0;
 
 	/* Early out if we are an invalid form of lswx */
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 0c0e714..9353584 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -145,6 +145,7 @@
   __init_end = .;
 
   . = ALIGN(4096);
+  _sextratext = .;
   __pmac_begin = .;
   .pmac.text : { *(.pmac.text) }
   .pmac.data : { *(.pmac.data) }
@@ -171,6 +172,7 @@
   .openfirmware.data : { *(.openfirmware.data) }
   . = ALIGN(4096);
   __openfirmware_end = .;
+  _eextratext = .;
 
   __bss_start = .;
   .bss       :
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
index f63bca8..cd11734 100644
--- a/arch/ppc/platforms/4xx/ebony.c
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -149,7 +149,7 @@
 static void __init
 ebony_setup_pcix(void)
 {
-	void *pcix_reg_base;
+	void __iomem *pcix_reg_base;
 
 	pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
 
@@ -210,9 +210,8 @@
 	hose->io_space.end = EBONY_PCI_UPPER_IO;
 	hose->mem_space.start = EBONY_PCI_LOWER_MEM;
 	hose->mem_space.end = EBONY_PCI_UPPER_MEM;
-	isa_io_base =
-		(unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE);
-	hose->io_base_virt = (void *)isa_io_base;
+	hose->io_base_virt = ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE);
+	isa_io_base = (unsigned long)hose->io_base_virt;
 
 	setup_indirect_pci(hose,
 			EBONY_PCI_CFGA_PLB32,
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
index 1df2339..95359f7 100644
--- a/arch/ppc/platforms/4xx/luan.c
+++ b/arch/ppc/platforms/4xx/luan.c
@@ -223,9 +223,8 @@
 	hose->io_space.end = LUAN_PCIX_UPPER_IO;
 	hose->mem_space.start = lower_mem;
 	hose->mem_space.end = upper_mem;
-	isa_io_base =
-		(unsigned long)ioremap64(pcix_io_base, PCIX_IO_SIZE);
-	hose->io_base_virt = (void *)isa_io_base;
+	hose->io_base_virt = ioremap64(pcix_io_base, PCIX_IO_SIZE);
+	isa_io_base = (unsigned long) hose->io_base_virt;
 
 	setup_indirect_pci(hose, cfga, cfgd);
 	hose->set_cfg_type = 1;
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index 28de707..5f82a6b 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -227,9 +227,8 @@
 	hose->io_space.end = OCOTEA_PCI_UPPER_IO;
 	hose->mem_space.start = OCOTEA_PCI_LOWER_MEM;
 	hose->mem_space.end = OCOTEA_PCI_UPPER_MEM;
-	isa_io_base =
-		(unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE);
-	hose->io_base_virt = (void *)isa_io_base;
+	hose->io_base_virt = ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE);
+	isa_io_base = (unsigned long) hose->io_base_virt;
 
 	setup_indirect_pci(hose,
 			OCOTEA_PCI_CFGA_PLB32,
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
index 5bb6492..7d0ee30 100644
--- a/arch/ppc/platforms/chrp_pci.c
+++ b/arch/ppc/platforms/chrp_pci.c
@@ -129,7 +129,7 @@
 	rtas_write_config
 };
 
-volatile struct Hydra *Hydra = NULL;
+volatile struct Hydra __iomem *Hydra = NULL;
 
 int __init
 hydra_init(void)
@@ -175,13 +175,14 @@
 static void __init
 setup_python(struct pci_controller *hose, struct device_node *dev)
 {
-	u32 *reg, val;
+	u32 __iomem *reg;
+	u32 val;
 	unsigned long addr = dev->addrs[0].address;
 
 	setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
 
 	/* Clear the magic go-slow bit */
-	reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40);
+	reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
 	val = in_be32(&reg[12]);
 	if (val & PRG_CL_RESET_VALID) {
 		out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
index f23c4f3..57f29ab 100644
--- a/arch/ppc/platforms/chrp_setup.c
+++ b/arch/ppc/platforms/chrp_setup.c
@@ -356,7 +356,7 @@
 	struct device_node *np;
 	int len, i;
 	unsigned int *iranges;
-	void *isu;
+	void __iomem *isu;
 
 	np = find_type_devices("open-pic");
 	if (np == NULL || np->n_addrs == 0)
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S
index da34a9b..fb977de 100644
--- a/arch/ppc/platforms/pmac_cache.S
+++ b/arch/ppc/platforms/pmac_cache.S
@@ -64,27 +64,39 @@
 	mtspr	SPRN_HID0,r4		/* Disable DPM */
 	sync
 
-	/* disp-flush L1 */
-	li	r4,0x4000
-	mtctr	r4
+	/* Disp-flush L1. We have a weird problem here that I never
+	 * totally figured out. On 750FX, using the ROM for the flush
+	 * results in a non-working flush. We use that workaround for
+	 * now until I finally understand what's going on. --BenH
+	 */
+
+	/* ROM base by default */
 	lis	r4,0xfff0
-1:	lwzx	r0,r0,r4
+	mfpvr	r3
+	srwi	r3,r3,16
+	cmplwi	cr0,r3,0x7000
+	bne+	1f
+	/* RAM base on 750FX */
+	li	r4,0
+1:	li	r4,0x4000
+	mtctr	r4
+1:	lwz	r0,0(r4)
 	addi	r4,r4,32
 	bdnz	1b
 	sync
 	isync
 
-	/* disable / invalidate / enable L1 data */
+	/* Disable / invalidate / enable L1 data */
 	mfspr	r3,SPRN_HID0
-	rlwinm	r0,r0,0,~HID0_DCE
+	rlwinm	r3,r3,0,~(HID0_DCE | HID0_ICE)
 	mtspr	SPRN_HID0,r3
 	sync
 	isync
-	ori	r3,r3,HID0_DCE|HID0_DCI
+	ori	r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)
 	sync
 	isync
 	mtspr	SPRN_HID0,r3
-	xori	r3,r3,HID0_DCI
+	xori	r3,r3,(HID0_DCI|HID0_ICFI)
 	mtspr	SPRN_HID0,r3
 	sync
 
@@ -110,11 +122,20 @@
 	lis	r4,2
 	mtctr	r4
 	lis	r4,0xfff0
-1:	lwzx	r0,r0,r4
+1:	lwz	r0,0(r4)
 	addi	r4,r4,32
 	bdnz	1b
 	sync
 	isync
+	lis	r4,2
+	mtctr	r4
+	lis	r4,0xfff0
+1:	dcbf	0,r4
+	addi	r4,r4,32
+	bdnz	1b
+	sync
+	isync
+
 	/* now disable L2 */
 	rlwinm	r5,r5,0,~L2CR_L2E
 	b	2f
@@ -135,6 +156,13 @@
 	mtspr	SPRN_L2CR,r4
 	sync
 	isync
+
+	/* Wait for the invalidation to complete */
+1:	mfspr	r3,SPRN_L2CR
+	rlwinm.	r0,r3,0,31,31
+	bne	1b
+
+	/* Clear L2I */
 	xoris	r4,r4,L2CR_L2I@h
 	sync
 	mtspr	SPRN_L2CR,r4
@@ -142,14 +170,16 @@
 
 	/* now disable the L1 data cache */
 	mfspr	r0,SPRN_HID0
-	rlwinm	r0,r0,0,~HID0_DCE
+	rlwinm	r0,r0,0,~(HID0_DCE|HID0_ICE)
 	mtspr	SPRN_HID0,r0
 	sync
 	isync
 
 	/* Restore HID0[DPM] to whatever it was before */
 	sync
-	mtspr	SPRN_HID0,r8
+	mfspr	r0,SPRN_HID0
+	rlwimi	r0,r8,0,11,11		/* Turn back HID0[DPM] */
+	mtspr	SPRN_HID0,r0
 	sync
 
 	/* restore DR and EE */
@@ -201,7 +231,7 @@
         mtctr   r4
  	li      r4,0
 1:
-        lwzx    r0,r0,r4
+        lwz     r0,0(r4)
         addi    r4,r4,32                /* Go to start of next cache line */
         bdnz    1b
         isync
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
index 46cbf36..867336a 100644
--- a/arch/ppc/platforms/pmac_feature.c
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -1590,6 +1590,114 @@
 	mdelay(10);
 }
 
+
+void __pmac pmac_tweak_clock_spreading(int enable)
+{
+	struct macio_chip* macio = &macio_chips[0];
+
+	/* Hack for doing clock spreading on some machines PowerBooks and
+	 * iBooks. This implements the "platform-do-clockspreading" OF
+	 * property as decoded manually on various models. For safety, we also
+	 * check the product ID in the device-tree in cases we'll whack the i2c
+	 * chip to make reasonably sure we won't set wrong values in there
+	 *
+	 * Of course, ultimately, we have to implement a real parser for
+	 * the platform-do-* stuff...
+	 */
+
+	if (macio->type == macio_intrepid) {
+		if (enable)
+			UN_OUT(UNI_N_CLOCK_SPREADING, 2);
+		else
+			UN_OUT(UNI_N_CLOCK_SPREADING, 0);
+		mdelay(40);
+	}
+
+	while (machine_is_compatible("PowerBook5,2") ||
+	       machine_is_compatible("PowerBook5,3") ||
+	       machine_is_compatible("PowerBook6,2") ||
+	       machine_is_compatible("PowerBook6,3")) {
+		struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
+		struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
+		u8 buffer[9];
+		u32 *productID;
+		int i, rc, changed = 0;
+
+		if (dt == NULL)
+			break;
+		productID = (u32 *)get_property(dt, "pid#", NULL);
+		if (productID == NULL)
+			break;
+		while(ui2c) {
+			struct device_node *p = of_get_parent(ui2c);
+			if (p && !strcmp(p->name, "uni-n"))
+				break;
+			ui2c = of_find_node_by_type(ui2c, "i2c");
+		}
+		if (ui2c == NULL)
+			break;
+		DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
+		rc = pmac_low_i2c_open(ui2c, 1);
+		if (rc != 0)
+			break;
+		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
+		DBG("read result: %d,", rc);
+		if (rc != 0) {
+			pmac_low_i2c_close(ui2c);
+			break;
+		}
+		for (i=0; i<9; i++)
+			DBG(" %02x", buffer[i]);
+		DBG("\n");
+
+		switch(*productID) {
+		case 0x1182:	/* AlBook 12" rev 2 */
+		case 0x1183:	/* iBook G4 12" */
+			buffer[0] = (buffer[0] & 0x8f) | 0x70;
+			buffer[2] = (buffer[2] & 0x7f) | 0x00;
+			buffer[5] = (buffer[5] & 0x80) | 0x31;
+			buffer[6] = (buffer[6] & 0x40) | 0xb0;
+			buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
+			buffer[8] = (buffer[8] & 0x00) | 0x30;
+			changed = 1;
+			break;
+		case 0x3142:	/* AlBook 15" (ATI M10) */
+		case 0x3143:	/* AlBook 17" (ATI M10) */
+			buffer[0] = (buffer[0] & 0xaf) | 0x50;
+			buffer[2] = (buffer[2] & 0x7f) | 0x00;
+			buffer[5] = (buffer[5] & 0x80) | 0x31;
+			buffer[6] = (buffer[6] & 0x40) | 0xb0;
+			buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
+			buffer[8] = (buffer[8] & 0x00) | 0x30;
+			changed = 1;
+			break;
+		default:
+			DBG("i2c-hwclock: Machine model not handled\n");
+			break;
+		}
+		if (!changed) {
+			pmac_low_i2c_close(ui2c);
+			break;
+		}
+		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
+		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
+		DBG("write result: %d,", rc);
+		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
+		DBG("read result: %d,", rc);
+		if (rc != 0) {
+			pmac_low_i2c_close(ui2c);
+			break;
+		}
+		for (i=0; i<9; i++)
+			DBG(" %02x", buffer[i]);
+		pmac_low_i2c_close(ui2c);
+		break;
+	}
+}
+
+
 static int __pmac
 core99_sleep(void)
 {
@@ -1601,12 +1709,6 @@
 	    macio->type != macio_intrepid)
 		return -ENODEV;
 
-	/* The device-tree contains that in the hwclock node */
-	if (macio->type == macio_intrepid) {
-		UN_OUT(UNI_N_CLOCK_SPREADING, 0);
-		mdelay(40);
-	}
-
 	/* We power off the wireless slot in case it was not done
 	 * by the driver. We don't power it on automatically however
 	 */
@@ -1749,12 +1851,6 @@
 	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
 	udelay(100);
 
-	/* Restore clock spreading */
-	if (macio->type == macio_intrepid) {
-		UN_OUT(UNI_N_CLOCK_SPREADING, 2);
-		mdelay(40);
-	}
-
 	return 0;
 }
 
@@ -2149,7 +2245,7 @@
 	},
 	{	"PowerBook1,1",			"PowerBook 101 (Lombard)",
 		PMAC_TYPE_101_PBOOK,		paddington_features,
-		PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE
+		PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
 	},
 	{	"PowerBook2,1",			"iBook (first generation)",
 		PMAC_TYPE_ORIG_IBOOK,		core99_features,
@@ -2718,97 +2814,11 @@
 		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
 	}
 
-	/* Hack for bumping clock speed on the new PowerBooks and the
-	 * iBook G4. This implements the "platform-do-clockspreading" OF
-	 * property. For safety, we also check the product ID in the
-	 * device-tree to make reasonably sure we won't set wrong values
-	 * in the clock chip.
-	 *
-	 * Of course, ultimately, we have to implement a real parser for
-	 * the platform-do-* stuff...
+	/* Some machine models need the clock chip to be properly setup for
+	 * clock spreading now. This should be a platform function but we
+	 * don't do these at the moment
 	 */
-	while (machine_is_compatible("PowerBook5,2") ||
-	       machine_is_compatible("PowerBook5,3") ||
-	       machine_is_compatible("PowerBook6,2") ||
-	       machine_is_compatible("PowerBook6,3")) {
-		struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
-		struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
-		u8 buffer[9];
-		u32 *productID;
-		int i, rc, changed = 0;
-		
-		if (dt == NULL)
-			break;
-		productID = (u32 *)get_property(dt, "pid#", NULL);
-		if (productID == NULL)
-			break;
-		while(ui2c) {
-			struct device_node *p = of_get_parent(ui2c);
-			if (p && !strcmp(p->name, "uni-n"))
-				break;
-			ui2c = of_find_node_by_type(ui2c, "i2c");
-		}
-		if (ui2c == NULL)
-			break;
-		DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
-		rc = pmac_low_i2c_open(ui2c, 1);
-		if (rc != 0)
-			break;
-		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
-		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
-		DBG("read result: %d,", rc);
-		if (rc != 0) {
-			pmac_low_i2c_close(ui2c);
-			break;
-		}
-		for (i=0; i<9; i++)
-			DBG(" %02x", buffer[i]);
-		DBG("\n");
-		
-		switch(*productID) {
-		case 0x1182:	/* AlBook 12" rev 2 */
-		case 0x1183:	/* iBook G4 12" */
-			buffer[0] = (buffer[0] & 0x8f) | 0x70;
-			buffer[2] = (buffer[2] & 0x7f) | 0x00;
-			buffer[5] = (buffer[5] & 0x80) | 0x31;
-			buffer[6] = (buffer[6] & 0x40) | 0xb0;
-			buffer[7] = (buffer[7] & 0x00) | 0xc0;
-			buffer[8] = (buffer[8] & 0x00) | 0x30;
-			changed = 1;
-			break;
-		case 0x3142:	/* AlBook 15" (ATI M10) */
-		case 0x3143:	/* AlBook 17" (ATI M10) */
-			buffer[0] = (buffer[0] & 0xaf) | 0x50;
-			buffer[2] = (buffer[2] & 0x7f) | 0x00;
-			buffer[5] = (buffer[5] & 0x80) | 0x31;
-			buffer[6] = (buffer[6] & 0x40) | 0xb0;
-			buffer[7] = (buffer[7] & 0x00) | 0xd0;
-			buffer[8] = (buffer[8] & 0x00) | 0x30;
-			changed = 1;
-			break;
-		default:
-			DBG("i2c-hwclock: Machine model not handled\n");
-			break;
-		}
-		if (!changed) {
-			pmac_low_i2c_close(ui2c);
-			break;
-		}
-		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
-		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
-		DBG("write result: %d,", rc);
-		pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
-		rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
-		DBG("read result: %d,", rc);
-		if (rc != 0) {
-			pmac_low_i2c_close(ui2c);
-			break;
-		}
-		for (i=0; i<9; i++)
-			DBG(" %02x", buffer[i]);
-		pmac_low_i2c_close(ui2c);
-		break;
-	}
+	pmac_tweak_clock_spreading(1);
 
 #endif /* CONFIG_POWER4 */
 
diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c
index d07579f..08583fc 100644
--- a/arch/ppc/platforms/pmac_low_i2c.c
+++ b/arch/ppc/platforms/pmac_low_i2c.c
@@ -54,7 +54,7 @@
 	int			mode;		/* Current mode */
 	int			channel;	/* Current channel */
 	int			num_channels;	/* Number of channels */
-	unsigned long		base;		/* For keywest-i2c, base address */
+	void __iomem *		base;		/* For keywest-i2c, base address */
 	int			bsteps;		/* And register stepping */
 	int			speed;		/* And speed */
 };
@@ -154,14 +154,12 @@
 
 static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
 {
-	return in_8(((volatile u8 *)host->base)
-		+ (((unsigned)reg) << host->bsteps));
+	return in_8(host->base + (((unsigned)reg) << host->bsteps));
 }
 
 static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
 {
-	out_8(((volatile u8 *)host->base)
-		+ (((unsigned)reg) << host->bsteps), val);
+	out_8(host->base + (((unsigned)reg) << host->bsteps), val);
 	(void)__kw_read_reg(host, reg_subaddr);
 }
 
@@ -370,7 +368,7 @@
 		break;
 	}	
 	host->mode = pmac_low_i2c_mode_std;
-	host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset,
+	host->base = ioremap(np->addrs[0].address + aoffset,
 						np->addrs[0].size);
 	host->func = keywest_low_i2c_func;
 }
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
index 3139b67..f459ade 100644
--- a/arch/ppc/platforms/pmac_sleep.S
+++ b/arch/ppc/platforms/pmac_sleep.S
@@ -267,6 +267,10 @@
 	/* Restore various CPU config stuffs */
 	bl	__restore_cpu_setup
 
+	/* Make sure all FPRs have been initialized */
+	bl	reloc_offset
+	bl	__init_fpu_registers
+
 	/* Invalidate & enable L1 cache, we don't care about
 	 * whatever the ROM may have tried to write to memory
 	 */
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index 731841f..8e049da 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -91,11 +91,11 @@
 #define PSURGE_QUAD_BIC(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
 
 /* virtual addresses for the above */
-static volatile u8 *hhead_base;
-static volatile u8 *quad_base;
-static volatile u32 *psurge_pri_intr;
-static volatile u8 *psurge_sec_intr;
-static volatile u32 *psurge_start;
+static volatile u8 __iomem *hhead_base;
+static volatile u8 __iomem *quad_base;
+static volatile u32 __iomem *psurge_pri_intr;
+static volatile u8 __iomem *psurge_sec_intr;
+static volatile u32 __iomem *psurge_start;
 
 /* values for psurge_type */
 #define PSURGE_NONE		-1
@@ -322,10 +322,10 @@
 		/* All released cards using this HW design have 4 CPUs */
 		ncpus = 4;
 	} else {
-		iounmap((void *) quad_base);
+		iounmap(quad_base);
 		if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
 			/* not a dual-cpu card */
-			iounmap((void *) hhead_base);
+			iounmap(hhead_base);
 			psurge_type = PSURGE_NONE;
 			return 1;
 		}
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
index 0963654..de60ccc 100644
--- a/arch/ppc/platforms/pmac_time.c
+++ b/arch/ppc/platforms/pmac_time.c
@@ -165,7 +165,7 @@
 via_calibrate_decr(void)
 {
 	struct device_node *vias;
-	volatile unsigned char *via;
+	volatile unsigned char __iomem *via;
 	int count = VIA_TIMER_FREQ_6 / 100;
 	unsigned int dstart, dend;
 
@@ -176,8 +176,7 @@
 		vias = find_devices("via");
 	if (vias == 0 || vias->n_addrs == 0)
 		return 0;
-	via = (volatile unsigned char *)
-		ioremap(vias->addrs[0].address, vias->addrs[0].size);
+	via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
 
 	/* set timer 1 for continuous interrupts */
 	out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
@@ -202,7 +201,7 @@
 	printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
 	       tb_ticks_per_jiffy, dstart - dend);
 
-	iounmap((void*)via);
+	iounmap(via);
 	
 	return 1;
 }
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
index 2a99b43..c30607a 100644
--- a/arch/ppc/platforms/radstone_ppc7d.c
+++ b/arch/ppc/platforms/radstone_ppc7d.c
@@ -68,6 +68,7 @@
 #define PPC7D_RST_PIN			17 	/* GPP17 */
 
 extern u32 mv64360_irq_base;
+extern spinlock_t rtc_lock;
 
 static struct mv64x60_handle bh;
 static int ppc7d_has_alma;
@@ -75,6 +76,11 @@
 extern void gen550_progress(char *, unsigned short);
 extern void gen550_init(int, struct uart_port *);
 
+/* FIXME - move to h file */
+extern int ds1337_do_command(int id, int cmd, void *arg);
+#define DS1337_GET_DATE         0
+#define DS1337_SET_DATE         1
+
 /* residual data */
 unsigned char __res[sizeof(bd_t)];
 
@@ -253,6 +259,8 @@
 	u8 val1, val2;
 	static int flash_sizes[4] = { 64, 32, 0, 16 };
 	static int flash_banks[4] = { 4, 3, 2, 1 };
+	static int sdram_bank_sizes[4] = { 128, 256, 512, 1 };
+	int sdram_num_banks = 2;
 	static char *pci_modes[] = { "PCI33", "PCI66",
 		"Unknown", "Unknown",
 		"PCIX33", "PCIX66",
@@ -279,13 +287,17 @@
 		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 :
 		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0);
 
+	val = inb(PPC7D_CPLD_MEM_CONFIG);
+	if (val & PPC7D_CPLD_SDRAM_BANK_NUM_MASK) sdram_num_banks--;
+
 	val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND);
-	val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK;
-	seq_printf(m, "SDRAM\t\t: %d%c",
-		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 :
-		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 :
-		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1,
-		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M');
+	val1 = (val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK) >> 6;
+	seq_printf(m, "SDRAM\t\t: %d banks of %d%c, total %d%c",
+		   sdram_num_banks,
+		   sdram_bank_sizes[val1],
+		   (sdram_bank_sizes[val1] < 128) ? 'G' : 'M',
+		   sdram_num_banks * sdram_bank_sizes[val1],
+		   (sdram_bank_sizes[val1] < 128) ? 'G' : 'M');
 	if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) {
 		seq_printf(m, " [ECC %sabled]",
 			   (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" :
@@ -1236,6 +1248,38 @@
 	printk(KERN_INFO "Radstone Technology PPC7D\n");
 	if (ppc_md.progress)
 		ppc_md.progress("ppc7d_setup_arch: exit", 0);
+
+}
+
+/* Real Time Clock support.
+ * PPC7D has a DS1337 accessed by I2C.
+ */
+static ulong ppc7d_get_rtc_time(void)
+{
+        struct rtc_time tm;
+        int result;
+
+        spin_lock(&rtc_lock);
+        result = ds1337_do_command(0, DS1337_GET_DATE, &tm);
+        spin_unlock(&rtc_lock);
+
+        if (result == 0)
+                result = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+        return result;
+}
+
+static int ppc7d_set_rtc_time(unsigned long nowtime)
+{
+        struct rtc_time tm;
+        int result;
+
+        spin_lock(&rtc_lock);
+        to_tm(nowtime, &tm);
+        result = ds1337_do_command(0, DS1337_SET_DATE, &tm);
+        spin_unlock(&rtc_lock);
+
+        return result;
 }
 
 /* This kernel command line parameter can be used to have the target
@@ -1293,6 +1337,10 @@
 	data8 |= 0x07;
 	outb(data8, PPC7D_CPLD_LEDS);
 
+        /* Hook up RTC. We couldn't do this earlier because we need the I2C subsystem */
+        ppc_md.set_rtc_time = ppc7d_set_rtc_time;
+        ppc_md.get_rtc_time = ppc7d_get_rtc_time;
+
 	pr_debug("%s: exit\n", __FUNCTION__);
 }
 
diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h
index 4546fff2..9383755 100644
--- a/arch/ppc/platforms/radstone_ppc7d.h
+++ b/arch/ppc/platforms/radstone_ppc7d.h
@@ -240,6 +240,7 @@
 #define PPC7D_CPLD_FLASH_CNTL			0x086E
 
 /* MEMORY_CONFIG_EXTEND */
+#define PPC7D_CPLD_SDRAM_BANK_NUM_MASK		0x02
 #define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK		0xc0
 #define PPC7D_CPLD_SDRAM_BANK_SIZE_128M		0
 #define PPC7D_CPLD_SDRAM_BANK_SIZE_256M		0x40
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index 954b07f..c867be6 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -107,6 +107,11 @@
 		simr = &(cpm2_immr->im_intctl.ic_simrh);
 		ppc_cached_irq_mask[word] |= 1 << bit;
 		simr[word] = ppc_cached_irq_mask[word];
+		/*
+		 * Work around large numbers of spurious IRQs on PowerPC 82xx
+		 * systems.
+		 */
+		mb();
 	}
 }
 
diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c
index bd564fb..057cc3f 100644
--- a/arch/ppc/syslib/m8260_pci.c
+++ b/arch/ppc/syslib/m8260_pci.c
@@ -171,10 +171,9 @@
 	m8260_setup_pci(hose);
         hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
 
-        isa_io_base =
-                (unsigned long) ioremap(MPC826x_PCI_IO_BASE,
+        hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE,
                                         MPC826x_PCI_IO_SIZE);
-        hose->io_base_virt = (void *) isa_io_base;
+        isa_io_base = (unsigned long) hose->io_base_virt;
  
         /* setup resources */
         pci_init_resource(&hose->mem_resources[0],
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index c723efd..59cf3e8 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -205,13 +205,11 @@
 
 	hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
 
-	isa_io_base =
-		(unsigned long) ioremap(MPC52xx_PCI_IO_BASE,
-					MPC52xx_PCI_IO_SIZE);
-	hose->io_base_virt = (void *) isa_io_base;
+	hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
+	isa_io_base = (unsigned long) hose->io_base_virt;
 
 	hose->cfg_addr = &pci_regs->car;
-	hose->cfg_data = (void __iomem *) isa_io_base;
+	hose->cfg_data = hose->io_base_virt;
 
 	/* Setup resources */
 	pci_init_resource(&hose->mem_resources[0],
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
index 81f1968..152c3ef 100644
--- a/arch/ppc/syslib/ppc85xx_setup.c
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -280,16 +280,14 @@
 	hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
 	hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
 #ifdef CONFIG_85xx_PCI2
-	isa_io_base =
-		(unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+	hose_a->io_base_virt =  ioremap(MPC85XX_PCI1_IO_BASE,
 					MPC85XX_PCI1_IO_SIZE +
 					MPC85XX_PCI2_IO_SIZE);
 #else
-	isa_io_base =
-		(unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+	hose_a->io_base_virt =  ioremap(MPC85XX_PCI1_IO_BASE,
 					MPC85XX_PCI1_IO_SIZE);
 #endif
-	hose_a->io_base_virt = (void *) isa_io_base;
+	isa_io_base = (unsigned long)hose_a->io_base_virt;
 
 	/* setup resources */
 	pci_init_resource(&hose_a->mem_resources[0],
@@ -329,8 +327,8 @@
 	hose_b->io_space.start = MPC85XX_PCI2_LOWER_IO;
 	hose_b->io_space.end = MPC85XX_PCI2_UPPER_IO;
 	hose_b->io_base_phys = MPC85XX_PCI2_IO_BASE;
-	hose_b->io_base_virt = (void *) isa_io_base + MPC85XX_PCI1_IO_SIZE;
-
+	hose_b->io_base_virt = hose_a->io_base_virt + MPC85XX_PCI1_IO_SIZE;
+	
 	/* setup resources */
 	pci_init_resource(&hose_b->mem_resources[0],
 			MPC85XX_PCI2_LOWER_MEM,
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index ef1f05e..5cb3438 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -40,6 +40,10 @@
 	bool
 	default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+	bool
+	default y
+
 # We optimistically allocate largepages from the VM, so make the limit
 # large enough (16MB). This badly named config option is actually
 # max order + 1
@@ -258,6 +262,7 @@
 config RTAS_PROC
 	bool "Proc interface to RTAS"
 	depends on PPC_RTAS
+	default y
 
 config RTAS_FLASH
 	tristate "Firmware flash interface"
@@ -293,6 +298,9 @@
 
 endmenu
 
+config ISA_DMA_API
+	bool
+	default y
 
 menu "General setup"
 
diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
index e341a12..46b1ce5 100644
--- a/arch/ppc64/Kconfig.debug
+++ b/arch/ppc64/Kconfig.debug
@@ -5,6 +5,9 @@
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
+	help
+	  This option will cause messages to be printed if free stack space
+	  drops below a certain limit.
 
 config KPROBES
 	bool "Kprobes"
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index d33e20b..691f300 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -56,13 +56,20 @@
 CFLAGS		+= -msoft-float -pipe -mminimal-toc -mtraceback=none \
 		   -mcall-aixdesc
 
+GCC_VERSION     := $(call cc-version)
+GCC_BROKEN_VEC	:= $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;)
+
 ifeq ($(CONFIG_POWER4_ONLY),y)
 ifeq ($(CONFIG_ALTIVEC),y)
+ifeq ($(GCC_BROKEN_VEC),y)
 	CFLAGS += $(call cc-option,-mcpu=970)
 else
 	CFLAGS += $(call cc-option,-mcpu=power4)
 endif
 else
+	CFLAGS += $(call cc-option,-mcpu=power4)
+endif
+else
 	CFLAGS += $(call cc-option,-mtune=power4)
 endif
 
diff --git a/arch/ppc64/boot/addnote.c b/arch/ppc64/boot/addnote.c
index 66ff810..719663a 100644
--- a/arch/ppc64/boot/addnote.c
+++ b/arch/ppc64/boot/addnote.c
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <string.h>
 
+/* CHRP note section */
 char arch[] = "PowerPC";
 
 #define N_DESCR	6
@@ -31,6 +32,29 @@
 	0x4000,			/* load-base */
 };
 
+/* RPA note section */
+char rpaname[] = "IBM,RPA-Client-Config";
+
+/*
+ * Note: setting ignore_my_client_config *should* mean that OF ignores
+ * all the other fields, but there is a firmware bug which means that
+ * it looks at the splpar field at least.  So these values need to be
+ * reasonable.
+ */
+#define N_RPA_DESCR	8
+unsigned int rpanote[N_RPA_DESCR] = {
+	0,			/* lparaffinity */
+	64,			/* min_rmo_size */
+	0,			/* min_rmo_percent */
+	40,			/* max_pft_size */
+	1,			/* splpar */
+	-1,			/* min_load */
+	0,			/* new_mem_def */
+	1,			/* ignore_my_client_config */
+};
+
+#define ROUNDUP(len)	(((len) + 3) & ~3)
+
 unsigned char buf[512];
 
 #define GET_16BE(off)	((buf[off] << 8) + (buf[(off)+1]))
@@ -69,7 +93,7 @@
 {
 	int fd, n, i;
 	int ph, ps, np;
-	int nnote, ns;
+	int nnote, nnote2, ns;
 
 	if (ac != 2) {
 		fprintf(stderr, "Usage: %s elf-file\n", av[0]);
@@ -81,7 +105,8 @@
 		exit(1);
 	}
 
-	nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+	nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr);
+	nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote);
 
 	n = read(fd, buf, sizeof(buf));
 	if (n < 0) {
@@ -104,7 +129,7 @@
 	np = GET_16BE(E_PHNUM);
 	if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
 		goto notelf;
-	if (ph + (np + 1) * ps + nnote > n)
+	if (ph + (np + 2) * ps + nnote + nnote2 > n)
 		goto nospace;
 
 	for (i = 0; i < np; ++i) {
@@ -117,12 +142,12 @@
 	}
 
 	/* XXX check that the area we want to use is all zeroes */
-	for (i = 0; i < ps + nnote; ++i)
+	for (i = 0; i < 2 * ps + nnote + nnote2; ++i)
 		if (buf[ph + i] != 0)
 			goto nospace;
 
 	/* fill in the program header entry */
-	ns = ph + ps;
+	ns = ph + 2 * ps;
 	PUT_32BE(ph + PH_TYPE, PT_NOTE);
 	PUT_32BE(ph + PH_OFFSET, ns);
 	PUT_32BE(ph + PH_FILESZ, nnote);
@@ -134,11 +159,26 @@
 	PUT_32BE(ns + 8, 0x1275);
 	strcpy(&buf[ns + 12], arch);
 	ns += 12 + strlen(arch) + 1;
-	for (i = 0; i < N_DESCR; ++i)
-		PUT_32BE(ns + i * 4, descr[i]);
+	for (i = 0; i < N_DESCR; ++i, ns += 4)
+		PUT_32BE(ns, descr[i]);
+
+	/* fill in the second program header entry and the RPA note area */
+	ph += ps;
+	PUT_32BE(ph + PH_TYPE, PT_NOTE);
+	PUT_32BE(ph + PH_OFFSET, ns);
+	PUT_32BE(ph + PH_FILESZ, nnote2);
+
+	/* fill in the note area we point to */
+	PUT_32BE(ns, strlen(rpaname) + 1);
+	PUT_32BE(ns + 4, sizeof(rpanote));
+	PUT_32BE(ns + 8, 0x12759999);
+	strcpy(&buf[ns + 12], rpaname);
+	ns += 12 + ROUNDUP(strlen(rpaname) + 1);
+	for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
+		PUT_32BE(ns, rpanote[i]);
 
 	/* Update the number of program headers */
-	PUT_16BE(E_PHNUM, np + 1);
+	PUT_16BE(E_PHNUM, np + 2);
 
 	/* write back */
 	lseek(fd, (long) 0, SEEK_SET);
@@ -155,11 +195,11 @@
 	exit(0);
 
  notelf:
-	fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+	fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]);
 	exit(1);
 
  nospace:
 	fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
-		av[0]);
+		av[1]);
 	exit(1);
 }
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index b0fa86a..da12ea2 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -14,7 +14,6 @@
 #include <linux/string.h>
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 
 extern void *finddevice(const char *);
 extern int getprop(void *, const char *, void *, int);
diff --git a/arch/ppc64/boot/start.c b/arch/ppc64/boot/start.c
deleted file mode 100644
index ea247e7..0000000
--- a/arch/ppc64/boot/start.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <stdarg.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-
-#include <asm/div64.h>
-
-int (*prom)(void *);
-
-void *chosen_handle;
-void *stdin;
-void *stdout;
-void *stderr;
-
-void exit(void);
-void *finddevice(const char *name);
-int getprop(void *phandle, const char *name, void *buf, int buflen);
-void chrpboot(int a1, int a2, void *prom);	/* in main.c */
-
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
-	prom = (int (*)(void *)) promptr;
-	chosen_handle = finddevice("/chosen");
-	if (chosen_handle == (void *) -1)
-		exit();
-	if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
-		exit();
-	stderr = stdout;
-	if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
-	exit();
-
-	chrpboot(a1, a2, promptr);
-	for (;;)
-		exit();
-}
-
-int
-write(void *handle, void *ptr, int nb)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		void *ihandle;
-		void *addr;
-		int len;
-		int actual;
-	} args;
-
-	args.service = "write";
-	args.nargs = 3;
-	args.nret = 1;
-	args.ihandle = handle;
-	args.addr = ptr;
-	args.len = nb;
-	args.actual = -1;
-	(*prom)(&args);
-	return args.actual;
-}
-
-int
-read(void *handle, void *ptr, int nb)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		void *ihandle;
-		void *addr;
-		int len;
-		int actual;
-	} args;
-
-	args.service = "read";
-	args.nargs = 3;
-	args.nret = 1;
-	args.ihandle = handle;
-	args.addr = ptr;
-	args.len = nb;
-	args.actual = -1;
-	(*prom)(&args);
-	return args.actual;
-}
-
-void
-exit()
-{
-	struct prom_args {
-		char *service;
-	} args;
-
-	for (;;) {
-		args.service = "exit";
-		(*prom)(&args);
-	}
-}
-
-void
-pause(void)
-{
-	struct prom_args {
-		char *service;
-	} args;
-
-	args.service = "enter";
-	(*prom)(&args);
-}
-
-void *
-finddevice(const char *name)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		const char *devspec;
-		void *phandle;
-	} args;
-
-	args.service = "finddevice";
-	args.nargs = 1;
-	args.nret = 1;
-	args.devspec = name;
-	args.phandle = (void *) -1;
-	(*prom)(&args);
-	return args.phandle;
-}
-
-void *
-claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		unsigned int virt;
-		unsigned int size;
-		unsigned int align;
-		void *ret;
-	} args;
-
-	args.service = "claim";
-	args.nargs = 3;
-	args.nret = 1;
-	args.virt = virt;
-	args.size = size;
-	args.align = align;
-	(*prom)(&args);
-	return args.ret;
-}
-
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		void *phandle;
-		const char *name;
-		void *buf;
-		int buflen;
-		int size;
-	} args;
-
-	args.service = "getprop";
-	args.nargs = 4;
-	args.nret = 1;
-	args.phandle = phandle;
-	args.name = name;
-	args.buf = buf;
-	args.buflen = buflen;
-	args.size = -1;
-	(*prom)(&args);
-	return args.size;
-}
-
-int
-putc(int c, void *f)
-{
-	char ch = c;
-
-	if (c == '\n')
-		putc('\r', f);
-	return write(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
-	return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
-	int n = strlen(str);
-
-	return write(f, str, n) == n? 0: -1;
-}
-
-int
-readchar(void)
-{
-	char ch;
-
-	for (;;) {
-		switch (read(stdin, &ch, 1)) {
-		case 1:
-			return ch;
-		case -1:
-			printk("read(stdin) returned -1\r\n");
-			return -1;
-		}
-	}
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar(void)
-{
-	int c;
-
-	if (lineleft == 0) {
-		lineptr = line;
-		for (;;) {
-			c = readchar();
-			if (c == -1 || c == 4)
-				break;
-			if (c == '\r' || c == '\n') {
-				*lineptr++ = '\n';
-				putchar('\n');
-				break;
-			}
-			switch (c) {
-			case 0177:
-			case '\b':
-				if (lineptr > line) {
-					putchar('\b');
-					putchar(' ');
-					putchar('\b');
-					--lineptr;
-				}
-				break;
-			case 'U' & 0x1F:
-				while (lineptr > line) {
-					putchar('\b');
-					putchar(' ');
-					putchar('\b');
-					--lineptr;
-				}
-				break;
-			default:
-				if (lineptr >= &line[sizeof(line) - 1])
-					putchar('\a');
-				else {
-					putchar(c);
-					*lineptr++ = c;
-				}
-			}
-		}
-		lineleft = lineptr - line;
-		lineptr = line;
-	}
-	if (lineleft == 0)
-		return -1;
-	--lineleft;
-	return *lineptr++;
-}
-
-
-
-/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
-unsigned char _ctype[] = {
-_C,_C,_C,_C,_C,_C,_C,_C,			/* 0-7 */
-_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,		/* 8-15 */
-_C,_C,_C,_C,_C,_C,_C,_C,			/* 16-23 */
-_C,_C,_C,_C,_C,_C,_C,_C,			/* 24-31 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,			/* 32-39 */
-_P,_P,_P,_P,_P,_P,_P,_P,			/* 40-47 */
-_D,_D,_D,_D,_D,_D,_D,_D,			/* 48-55 */
-_D,_D,_P,_P,_P,_P,_P,_P,			/* 56-63 */
-_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,	/* 64-71 */
-_U,_U,_U,_U,_U,_U,_U,_U,			/* 72-79 */
-_U,_U,_U,_U,_U,_U,_U,_U,			/* 80-87 */
-_U,_U,_U,_P,_P,_P,_P,_P,			/* 88-95 */
-_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,	/* 96-103 */
-_L,_L,_L,_L,_L,_L,_L,_L,			/* 104-111 */
-_L,_L,_L,_L,_L,_L,_L,_L,			/* 112-119 */
-_L,_L,_L,_P,_P,_P,_P,_C,			/* 120-127 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 128-143 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 144-159 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
-_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
-_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
-_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
-_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
-_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
-
-size_t strnlen(const char * s, size_t count)
-{
-	const char *sc;
-
-	for (sc = s; count-- && *sc != '\0'; ++sc)
-		/* nothing */;
-	return sc - s;
-}
-
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
-{
-	unsigned long result = 0,value;
-
-	if (!base) {
-		base = 10;
-		if (*cp == '0') {
-			base = 8;
-			cp++;
-			if ((*cp == 'x') && isxdigit(cp[1])) {
-				cp++;
-				base = 16;
-			}
-		}
-	}
-	while (isxdigit(*cp) &&
-	       (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
-		result = result*base + value;
-		cp++;
-	}
-	if (endp)
-		*endp = (char *)cp;
-	return result;
-}
-
-long simple_strtol(const char *cp,char **endp,unsigned int base)
-{
-	if(*cp=='-')
-		return -simple_strtoul(cp+1,endp,base);
-	return simple_strtoul(cp,endp,base);
-}
-
-static int skip_atoi(const char **s)
-{
-	int i=0;
-
-	while (isdigit(**s))
-		i = i*10 + *((*s)++) - '0';
-	return i;
-}
-
-#define ZEROPAD	1		/* pad with zero */
-#define SIGN	2		/* unsigned/signed long */
-#define PLUS	4		/* show plus */
-#define SPACE	8		/* space if plus */
-#define LEFT	16		/* left justified */
-#define SPECIAL	32		/* 0x */
-#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * str, long long num, int base, int size, int precision, int type)
-{
-	char c,sign,tmp[66];
-	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
-	int i;
-
-	if (type & LARGE)
-		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-	if (type & LEFT)
-		type &= ~ZEROPAD;
-	if (base < 2 || base > 36)
-		return 0;
-	c = (type & ZEROPAD) ? '0' : ' ';
-	sign = 0;
-	if (type & SIGN) {
-		if (num < 0) {
-			sign = '-';
-			num = -num;
-			size--;
-		} else if (type & PLUS) {
-			sign = '+';
-			size--;
-		} else if (type & SPACE) {
-			sign = ' ';
-			size--;
-		}
-	}
-	if (type & SPECIAL) {
-		if (base == 16)
-			size -= 2;
-		else if (base == 8)
-			size--;
-	}
-	i = 0;
-	if (num == 0)
-		tmp[i++]='0';
-	else while (num != 0)
-		tmp[i++] = digits[do_div(num,base)];
-	if (i > precision)
-		precision = i;
-	size -= precision;
-	if (!(type&(ZEROPAD+LEFT)))
-		while(size-->0)
-			*str++ = ' ';
-	if (sign)
-		*str++ = sign;
-	if (type & SPECIAL) {
-		if (base==8)
-			*str++ = '0';
-		else if (base==16) {
-			*str++ = '0';
-			*str++ = digits[33];
-		}
-	}
-	if (!(type & LEFT))
-		while (size-- > 0)
-			*str++ = c;
-	while (i < precision--)
-		*str++ = '0';
-	while (i-- > 0)
-		*str++ = tmp[i];
-	while (size-- > 0)
-		*str++ = ' ';
-	return str;
-}
-
-/* Forward decl. needed for IP address printing stuff... */
-int sprintf(char * buf, const char *fmt, ...);
-
-int vsprintf(char *buf, const char *fmt, va_list args)
-{
-	int len;
-	unsigned long long num;
-	int i, base;
-	char * str;
-	const char *s;
-
-	int flags;		/* flags to number() */
-
-	int field_width;	/* width of output field */
-	int precision;		/* min. # of digits for integers; max
-				   number of chars for from string */
-	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
-	                        /* 'z' support added 23/7/1999 S.H.    */
-				/* 'z' changed to 'Z' --davidm 1/25/99 */
-
-	
-	for (str=buf ; *fmt ; ++fmt) {
-		if (*fmt != '%') {
-			*str++ = *fmt;
-			continue;
-		}
-			
-		/* process flags */
-		flags = 0;
-		repeat:
-			++fmt;		/* this also skips first '%' */
-			switch (*fmt) {
-				case '-': flags |= LEFT; goto repeat;
-				case '+': flags |= PLUS; goto repeat;
-				case ' ': flags |= SPACE; goto repeat;
-				case '#': flags |= SPECIAL; goto repeat;
-				case '0': flags |= ZEROPAD; goto repeat;
-				}
-		
-		/* get field width */
-		field_width = -1;
-		if (isdigit(*fmt))
-			field_width = skip_atoi(&fmt);
-		else if (*fmt == '*') {
-			++fmt;
-			/* it's the next argument */
-			field_width = va_arg(args, int);
-			if (field_width < 0) {
-				field_width = -field_width;
-				flags |= LEFT;
-			}
-		}
-
-		/* get the precision */
-		precision = -1;
-		if (*fmt == '.') {
-			++fmt;	
-			if (isdigit(*fmt))
-				precision = skip_atoi(&fmt);
-			else if (*fmt == '*') {
-				++fmt;
-				/* it's the next argument */
-				precision = va_arg(args, int);
-			}
-			if (precision < 0)
-				precision = 0;
-		}
-
-		/* get the conversion qualifier */
-		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
-			qualifier = *fmt;
-			++fmt;
-		}
-
-		/* default base */
-		base = 10;
-
-		switch (*fmt) {
-		case 'c':
-			if (!(flags & LEFT))
-				while (--field_width > 0)
-					*str++ = ' ';
-			*str++ = (unsigned char) va_arg(args, int);
-			while (--field_width > 0)
-				*str++ = ' ';
-			continue;
-
-		case 's':
-			s = va_arg(args, char *);
-			if (!s)
-				s = "<NULL>";
-
-			len = strnlen(s, precision);
-
-			if (!(flags & LEFT))
-				while (len < field_width--)
-					*str++ = ' ';
-			for (i = 0; i < len; ++i)
-				*str++ = *s++;
-			while (len < field_width--)
-				*str++ = ' ';
-			continue;
-
-		case 'p':
-			if (field_width == -1) {
-				field_width = 2*sizeof(void *);
-				flags |= ZEROPAD;
-			}
-			str = number(str,
-				(unsigned long) va_arg(args, void *), 16,
-				field_width, precision, flags);
-			continue;
-
-
-		case 'n':
-			if (qualifier == 'l') {
-				long * ip = va_arg(args, long *);
-				*ip = (str - buf);
-			} else if (qualifier == 'Z') {
-				size_t * ip = va_arg(args, size_t *);
-				*ip = (str - buf);
-			} else {
-				int * ip = va_arg(args, int *);
-				*ip = (str - buf);
-			}
-			continue;
-
-		case '%':
-			*str++ = '%';
-			continue;
-
-		/* integer number formats - set up the flags and "break" */
-		case 'o':
-			base = 8;
-			break;
-
-		case 'X':
-			flags |= LARGE;
-		case 'x':
-			base = 16;
-			break;
-
-		case 'd':
-		case 'i':
-			flags |= SIGN;
-		case 'u':
-			break;
-
-		default:
-			*str++ = '%';
-			if (*fmt)
-				*str++ = *fmt;
-			else
-				--fmt;
-			continue;
-		}
-		if (qualifier == 'L')
-			num = va_arg(args, long long);
-		else if (qualifier == 'l') {
-			num = va_arg(args, unsigned long);
-			if (flags & SIGN)
-				num = (signed long) num;
-		} else if (qualifier == 'Z') {
-			num = va_arg(args, size_t);
-		} else if (qualifier == 'h') {
-			num = (unsigned short) va_arg(args, int);
-			if (flags & SIGN)
-				num = (signed short) num;
-		} else {
-			num = va_arg(args, unsigned int);
-			if (flags & SIGN)
-				num = (signed int) num;
-		}
-		str = number(str, num, base, field_width, precision, flags);
-	}
-	*str = '\0';
-	return str-buf;
-}
-
-int sprintf(char * buf, const char *fmt, ...)
-{
-	va_list args;
-	int i;
-
-	va_start(args, fmt);
-	i=vsprintf(buf,fmt,args);
-	va_end(args);
-	return i;
-}
-
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	write(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	write(stdout, sprint_buf, n);
-	return n;
-}
diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c
index 9802bee..f8f1963 100644
--- a/arch/ppc64/kernel/HvLpEvent.c
+++ b/arch/ppc64/kernel/HvLpEvent.c
@@ -45,7 +45,7 @@
 			/* We now sleep until all other CPUs have scheduled. This ensures that
 			 * the deletion is seen by all other CPUs, and that the deleted handler
 			 * isn't still running on another CPU when we return. */
-			synchronize_kernel();
+			synchronize_rcu();
 		}
 	}
 	return rc;
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index 90b41f4..b944717 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -32,7 +32,7 @@
 	.text
 
 /*
- * Returns (address we're running at) - (address we were linked at)
+ * Returns (address we were linked at) - (address we are running at)
  * for use before the text and data are mapped to KERNELBASE.
  */
 
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
index b9069c2..4e71781 100644
--- a/arch/ppc64/kernel/nvram.c
+++ b/arch/ppc64/kernel/nvram.c
@@ -339,9 +339,9 @@
 static int nvram_create_os_partition(void)
 {
 	struct list_head * p;
-	struct nvram_partition * part;
-	struct nvram_partition * new_part = NULL;
-	struct nvram_partition * free_part = NULL;
+	struct nvram_partition *part = NULL;
+	struct nvram_partition *new_part = NULL;
+	struct nvram_partition *free_part = NULL;
 	int seq_init[2] = { 0, 0 };
 	loff_t tmp_index;
 	long size = 0;
@@ -364,13 +364,11 @@
 			free_part = part;
 		}
 	}
-	if (!size) {
+	if (!size)
 		return -ENOSPC;
-	}
 	
 	/* Create our OS partition */
-	new_part = (struct nvram_partition *)
-		kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+	new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
 	if (!new_part) {
 		printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
 		return -ENOMEM;
@@ -379,7 +377,7 @@
 	new_part->index = free_part->index;
 	new_part->header.signature = NVRAM_SIG_OS;
 	new_part->header.length = size;
-	sprintf(new_part->header.name, "ppc64,linux");
+	strcpy(new_part->header.name, "ppc64,linux");
 	new_part->header.checksum = nvram_checksum(&new_part->header);
 
 	rc = nvram_write_header(new_part);
@@ -394,7 +392,8 @@
 	tmp_index = new_part->index + NVRAM_HEADER_LEN;
 	rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write failed (%d)\n", rc);
+		printk(KERN_ERR "nvram_create_os_partition: nvram_write "
+				"failed (%d)\n", rc);
 		return rc;
 	}
 	
diff --git a/arch/ppc64/kernel/pSeries_hvCall.S b/arch/ppc64/kernel/pSeries_hvCall.S
index 0715d30..176e8da 100644
--- a/arch/ppc64/kernel/pSeries_hvCall.S
+++ b/arch/ppc64/kernel/pSeries_hvCall.S
@@ -28,6 +28,8 @@
 			unsigned long *out3);		R10
  */
 _GLOBAL(plpar_hcall)
+	HMT_MEDIUM
+
 	mfcr	r0
 
 	std	r8,STK_PARM(r8)(r1)	/* Save out ptrs */
@@ -53,6 +55,8 @@
 
 /* Simple interface with no output values (other than status) */
 _GLOBAL(plpar_hcall_norets)
+	HMT_MEDIUM
+
 	mfcr	r0
 	stw	r0,8(r1)
 
@@ -75,6 +79,8 @@
 			unsigned long *out1);		120(R1)
  */
 _GLOBAL(plpar_hcall_8arg_2ret)
+	HMT_MEDIUM
+
 	mfcr	r0
 	ld	r11,STK_PARM(r11)(r1)	/* put arg8 in R11 */
 	stw	r0,8(r1)
@@ -99,6 +105,8 @@
 		 	unsigned long *out4);		112(R1)
  */
 _GLOBAL(plpar_hcall_4out)
+	HMT_MEDIUM
+
 	mfcr	r0
 	stw	r0,8(r1)
 
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index c60d8cb..fbad349 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -326,13 +326,6 @@
 
 	cpu_clear(cpu, of_spin_map);
 
-	/*
-	 * Put the calling processor into the GIQ.  This is really only
-	 * necessary from a secondary thread as the OF start-cpu interface
-	 * performs this function for us on primary threads.
-	 */
-	rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
-		(1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
 }
 
 static DEFINE_SPINLOCK(timebase_lock);
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index be3cc38..d786d4b 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -438,7 +438,7 @@
 	int i;
 
 	if (page_is_ram(offset >> PAGE_SHIFT))
-		return prot;
+		return __pgprot(prot);
 
 	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
 
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 45a4ad0..eb6538b 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -321,6 +321,10 @@
 			char *name = get_property(ic->parent, "name", NULL);
 			if (name && !strcmp(name, "u3"))
 				np->intrs[intrcount].line += 128;
+			else if (!(name && !strcmp(name, "mac-io")))
+				/* ignore other cascaded controllers, such as
+				   the k2-sata-root */
+				break;
 		}
 		np->intrs[intrcount].sense = 1;
 		if (n > 1)
@@ -830,7 +834,7 @@
 {
 	unsigned long start, mem, size;
 	struct device_node **allnextp = &allnodes;
-	char *p;
+	char *p = NULL;
 	int l = 0;
 
 	DBG(" -> unflatten_device_tree()\n");
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 8dffa9a..35ec42d 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -493,6 +493,113 @@
 }
 
 /*
+ * To tell the firmware what our capabilities are, we have to pass
+ * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
+ * that contain structures that contain the actual values.
+ */
+static struct fake_elf {
+	Elf32_Ehdr	elfhdr;
+	Elf32_Phdr	phdr[2];
+	struct chrpnote {
+		u32	namesz;
+		u32	descsz;
+		u32	type;
+		char	name[8];	/* "PowerPC" */
+		struct chrpdesc {
+			u32	real_mode;
+			u32	real_base;
+			u32	real_size;
+			u32	virt_base;
+			u32	virt_size;
+			u32	load_base;
+		} chrpdesc;
+	} chrpnote;
+	struct rpanote {
+		u32	namesz;
+		u32	descsz;
+		u32	type;
+		char	name[24];	/* "IBM,RPA-Client-Config" */
+		struct rpadesc {
+			u32	lpar_affinity;
+			u32	min_rmo_size;
+			u32	min_rmo_percent;
+			u32	max_pft_size;
+			u32	splpar;
+			u32	min_load;
+			u32	new_mem_def;
+			u32	ignore_me;
+		} rpadesc;
+	} rpanote;
+} fake_elf = {
+	.elfhdr = {
+		.e_ident = { 0x7f, 'E', 'L', 'F',
+			     ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
+		.e_type = ET_EXEC,	/* yeah right */
+		.e_machine = EM_PPC,
+		.e_version = EV_CURRENT,
+		.e_phoff = offsetof(struct fake_elf, phdr),
+		.e_phentsize = sizeof(Elf32_Phdr),
+		.e_phnum = 2
+	},
+	.phdr = {
+		[0] = {
+			.p_type = PT_NOTE,
+			.p_offset = offsetof(struct fake_elf, chrpnote),
+			.p_filesz = sizeof(struct chrpnote)
+		}, [1] = {
+			.p_type = PT_NOTE,
+			.p_offset = offsetof(struct fake_elf, rpanote),
+			.p_filesz = sizeof(struct rpanote)
+		}
+	},
+	.chrpnote = {
+		.namesz = sizeof("PowerPC"),
+		.descsz = sizeof(struct chrpdesc),
+		.type = 0x1275,
+		.name = "PowerPC",
+		.chrpdesc = {
+			.real_mode = ~0U,	/* ~0 means "don't care" */
+			.real_base = ~0U,
+			.real_size = ~0U,
+			.virt_base = ~0U,
+			.virt_size = ~0U,
+			.load_base = ~0U
+		},
+	},
+	.rpanote = {
+		.namesz = sizeof("IBM,RPA-Client-Config"),
+		.descsz = sizeof(struct rpadesc),
+		.type = 0x12759999,
+		.name = "IBM,RPA-Client-Config",
+		.rpadesc = {
+			.lpar_affinity = 0,
+			.min_rmo_size = 64,	/* in megabytes */
+			.min_rmo_percent = 0,
+			.max_pft_size = 48,	/* 2^48 bytes max PFT size */
+			.splpar = 1,
+			.min_load = ~0U,
+			.new_mem_def = 0
+		}
+	}
+};
+
+static void __init prom_send_capabilities(void)
+{
+	unsigned long offset = reloc_offset();
+	ihandle elfloader;
+	int ret;
+
+	elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
+	if (elfloader == 0) {
+		prom_printf("couldn't open /packages/elf-loader\n");
+		return;
+	}
+	ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
+			elfloader, ADDR(&fake_elf));
+	call_prom("close", 1, 0, elfloader);
+}
+
+/*
  * Memory allocation strategy... our layout is normally:
  *
  *  at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd
@@ -1448,6 +1555,12 @@
 	}
 }
 
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
 					unsigned long *mem_end)
 {
@@ -1457,7 +1570,7 @@
 	unsigned long soff;
 	unsigned char *valp;
 	unsigned long offset = reloc_offset();
-	char pname[32];
+	char pname[MAX_PROPERTY_NAME];
 	char *path;
 
 	path = RELOC(prom_scratch);
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 354a287..9f8c608 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -28,6 +28,7 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -162,7 +163,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -194,7 +195,7 @@
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		set_single_step(child);
@@ -304,14 +305,17 @@
 
 void do_syscall_trace_enter(struct pt_regs *regs)
 {
-	if (unlikely(current->audit_context))
-		audit_syscall_entry(current, regs->gpr[0],
-				    regs->gpr[3], regs->gpr[4],
-				    regs->gpr[5], regs->gpr[6]);
-
 	if (test_thread_flag(TIF_SYSCALL_TRACE)
 	    && (current->ptrace & PT_PTRACED))
 		do_syscall_trace();
+
+	if (unlikely(current->audit_context))
+		audit_syscall_entry(current,
+				    test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
+				    regs->gpr[0],
+				    regs->gpr[3], regs->gpr[4],
+				    regs->gpr[5], regs->gpr[6]);
+
 }
 
 void do_syscall_trace_leave(struct pt_regs *regs)
@@ -319,7 +323,9 @@
 	secure_computing(regs->gpr[0]);
 
 	if (unlikely(current->audit_context))
-		audit_syscall_exit(current, regs->result);
+		audit_syscall_exit(current, 
+				   (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+				   regs->result);
 
 	if ((test_thread_flag(TIF_SYSCALL_TRACE)
 	     || test_thread_flag(TIF_SINGLESTEP))
diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
index ee81b1b..1643642 100644
--- a/arch/ppc64/kernel/ptrace32.c
+++ b/arch/ppc64/kernel/ptrace32.c
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -293,7 +294,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -325,7 +326,7 @@
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		set_single_step(child);
diff --git a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c
index 3213837..923e2e2 100644
--- a/arch/ppc64/kernel/rtas_flash.c
+++ b/arch/ppc64/kernel/rtas_flash.c
@@ -218,7 +218,7 @@
 }
 
 /* Reading the proc file will show status (not the firmware contents) */
-static ssize_t rtas_flash_read(struct file *file, char *buf,
+static ssize_t rtas_flash_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -256,7 +256,7 @@
  * count is.  If the system is low on memory it will be just as well
  * that we fail....
  */
-static ssize_t rtas_flash_write(struct file *file, const char *buffer,
+static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
 				size_t count, loff_t *off)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -356,7 +356,7 @@
 	args_buf->status = rc;
 }
 
-static ssize_t manage_flash_read(struct file *file, char *buf,
+static ssize_t manage_flash_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -386,7 +386,7 @@
 	return msglen;
 }
 
-static ssize_t manage_flash_write(struct file *file, const char *buf,
+static ssize_t manage_flash_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *off)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -466,7 +466,7 @@
 	return n;
 }
 
-static ssize_t validate_flash_read(struct file *file, char *buf,
+static ssize_t validate_flash_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *ppos)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -494,7 +494,7 @@
 	return msglen;
 }
 
-static ssize_t validate_flash_write(struct file *file, const char *buf,
+static ssize_t validate_flash_write(struct file *file, const char __user *buf,
 				    size_t count, loff_t *off)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
index 189b81a..4d70736 100644
--- a/arch/ppc64/kernel/scanlog.c
+++ b/arch/ppc64/kernel/scanlog.c
@@ -43,7 +43,7 @@
 static unsigned int ibm_scan_log_dump;			/* RTAS token */
 static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */
 
-static ssize_t scanlog_read(struct file *file, char *buf,
+static ssize_t scanlog_read(struct file *file, char __user *buf,
 			    size_t count, loff_t *ppos)
 {
         struct inode * inode = file->f_dentry->d_inode;
@@ -129,7 +129,7 @@
 	/*NOTREACHED*/
 }
 
-static ssize_t scanlog_write(struct file * file, const char * buf,
+static ssize_t scanlog_write(struct file * file, const char __user * buf,
 			     size_t count, loff_t *ppos)
 {
 	char stkbuf[20];
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
index a95a2b4..bf78227 100644
--- a/arch/ppc64/kernel/signal.c
+++ b/arch/ppc64/kernel/signal.c
@@ -42,11 +42,7 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-#define GP_REGS_SIZE	MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
+#define GP_REGS_SIZE	min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
 #define FP_REGS_SIZE	sizeof(elf_fpregset_t)
 
 #define TRAMP_TRACEBACK	3
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index b0e167d..3c2fa5c 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -657,7 +657,7 @@
 
 	/* Save user registers on the stack */
 	frame = &rt_sf->uc.uc_mcontext;
-	if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+	if (put_user(regs->gpr[1], (u32 __user *)newsp))
 		goto badframe;
 
 	if (vdso32_rt_sigtramp && current->thread.vdso_base) {
@@ -842,7 +842,7 @@
 		regs->link = (unsigned long) frame->mctx.tramp;
 	}
 
-	if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+	if (put_user(regs->gpr[1], (u32 __user *)newsp))
 		goto badframe;
 	regs->gpr[1] = (unsigned long) newsp;
 	regs->gpr[3] = sig;
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 1c92da3..3b906cd 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -125,7 +125,7 @@
 	 * the processor will continue on to secondary_start
 	 */
 	paca[nr].cpu_start = 1;
-	mb();
+	smp_mb();
 }
 
 #endif /* CONFIG_PPC_MULTIPLATFORM */
@@ -256,7 +256,7 @@
 	}
 
 	call_data = &data;
-	wmb();
+	smp_wmb();
 	/* Send a message to all other CPUs and wait for them to respond */
 	smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
 
@@ -431,7 +431,7 @@
 
 	/* get the target out of it's holding state */
 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
-	wmb();
+	smp_wmb();
 
 	while (!cpu_online(cpu))
 		cpu_relax();
@@ -447,7 +447,7 @@
 	int i;
 
 	for (i = 0; i < 100; i++) {
-		rmb();
+		smp_rmb();
 		if (per_cpu(cpu_state, cpu) == CPU_DEAD)
 			return;
 		msleep(100);
@@ -463,7 +463,7 @@
 	cpu = smp_processor_id();
 	printk(KERN_DEBUG "CPU%d offline\n", cpu);
 	__get_cpu_var(cpu_state) = CPU_DEAD;
-	wmb();
+	smp_wmb();
 	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
 		cpu_relax();
 
@@ -515,7 +515,7 @@
 	 * be written out to main store before we release
 	 * the processor.
 	 */
-	mb();
+	smp_mb();
 
 	/* wake up cpus */
 	DBG("smp: kicking cpu %d\n", cpu);
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 77ded5a..772a465 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -221,15 +221,15 @@
 	temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs;
 	temp_varp->tb_orig_stamp = new_tb_orig_stamp;
 	temp_varp->stamp_xsec = new_stamp_xsec;
-	mb();
+	smp_mb();
 	do_gtod.varp = temp_varp;
 	do_gtod.var_idx = temp_idx;
 
 	++(systemcfg->tb_update_count);
-	wmb();
+	smp_wmb();
 	systemcfg->tb_orig_stamp = new_tb_orig_stamp;
 	systemcfg->stamp_xsec = new_stamp_xsec;
-	wmb();
+	smp_wmb();
 	++(systemcfg->tb_update_count);
 }
 
@@ -648,7 +648,7 @@
 	temp_varp->tb_to_xs = new_tb_to_xs;
 	temp_varp->stamp_xsec = new_stamp_xsec;
 	temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp;
-	mb();
+	smp_mb();
 	do_gtod.varp = temp_varp;
 	do_gtod.var_idx = temp_idx;
 
@@ -662,10 +662,10 @@
 	 * loops back and reads them again until this criteria is met.
 	 */
 	++(systemcfg->tb_update_count);
-	wmb();
+	smp_wmb();
 	systemcfg->tb_to_xs = new_tb_to_xs;
 	systemcfg->stamp_xsec = new_stamp_xsec;
-	wmb();
+	smp_wmb();
 	++(systemcfg->tb_update_count);
 
 	write_sequnlock_irqrestore( &xtime_lock, flags );
diff --git a/arch/ppc64/kernel/vdso32/Makefile b/arch/ppc64/kernel/vdso32/Makefile
index ede2f7e..0b1b0df 100644
--- a/arch/ppc64/kernel/vdso32/Makefile
+++ b/arch/ppc64/kernel/vdso32/Makefile
@@ -1,7 +1,7 @@
 
 # List of files in the vdso, has to be asm only for now
 
-obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
 
 # Build rules
 
diff --git a/arch/ppc64/kernel/vdso32/cacheflush.S b/arch/ppc64/kernel/vdso32/cacheflush.S
index c74fddb..0ed7ea7 100644
--- a/arch/ppc64/kernel/vdso32/cacheflush.S
+++ b/arch/ppc64/kernel/vdso32/cacheflush.S
@@ -47,6 +47,7 @@
 	addi	r6,r6,128
 	bdnz	1b
 	isync
+	li	r3,0
 	blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache)
@@ -59,6 +60,7 @@
   .cfi_startproc
 	sync
 	isync
+	li	r3,0
 	blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache_p5)
diff --git a/arch/ppc64/kernel/vdso32/gettimeofday.S b/arch/ppc64/kernel/vdso32/gettimeofday.S
index ca7f415..2b48bf1 100644
--- a/arch/ppc64/kernel/vdso32/gettimeofday.S
+++ b/arch/ppc64/kernel/vdso32/gettimeofday.S
@@ -58,6 +58,7 @@
 	stw	r5,TZONE_TZ_DSTTIME(r11)
 
 1:	mtlr	r12
+	li	r3,0
 	blr
 
 2:	mr	r3,r10
diff --git a/arch/ppc64/kernel/vdso32/note.S b/arch/ppc64/kernel/vdso32/note.S
new file mode 100644
index 0000000..d4b5be4
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/note.S
@@ -0,0 +1,25 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+
+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type)			      \
+	.section name, flags;						      \
+	.balign 4;							      \
+	.long 1f - 0f;		/* name length */			      \
+	.long 3f - 2f;		/* data length */			      \
+	.long type;		/* note type */				      \
+0:	.asciz vendor;		/* vendor name */			      \
+1:	.balign 4;							      \
+2:
+
+#define ASM_ELF_NOTE_END						      \
+3:	.balign 4;		/* pad out section */			      \
+	.previous
+
+	ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
+	.long LINUX_VERSION_CODE
+	ASM_ELF_NOTE_END
diff --git a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/ppc64/kernel/vdso32/vdso32.lds.S
index cca27bd..11290c9 100644
--- a/arch/ppc64/kernel/vdso32/vdso32.lds.S
+++ b/arch/ppc64/kernel/vdso32/vdso32.lds.S
@@ -20,6 +20,8 @@
   .gnu.version_d  : { *(.gnu.version_d) }
   .gnu.version_r  : { *(.gnu.version_r) }
 
+  .note		  : { *(.note.*) } 			:text	:note
+
   . = ALIGN (16);
   .text :
   {
@@ -87,6 +89,7 @@
 PHDRS
 {
   text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  note PT_NOTE FLAGS(4); /* PF_R */
   dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
   eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
 }
diff --git a/arch/ppc64/kernel/vdso64/Makefile b/arch/ppc64/kernel/vdso64/Makefile
index bd3f70b..ab39988 100644
--- a/arch/ppc64/kernel/vdso64/Makefile
+++ b/arch/ppc64/kernel/vdso64/Makefile
@@ -1,6 +1,6 @@
 # List of files in the vdso, has to be asm only for now
 
-obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
 
 # Build rules
 
diff --git a/arch/ppc64/kernel/vdso64/cacheflush.S b/arch/ppc64/kernel/vdso64/cacheflush.S
index d9696ff..e0725b7 100644
--- a/arch/ppc64/kernel/vdso64/cacheflush.S
+++ b/arch/ppc64/kernel/vdso64/cacheflush.S
@@ -47,6 +47,7 @@
 	addi	r6,r6,128
 	bdnz	1b
 	isync
+	li	r3,0
 	blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache)
@@ -59,6 +60,7 @@
   .cfi_startproc
 	sync
 	isync
+	li	r3,0
 	blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache_p5)
diff --git a/arch/ppc64/kernel/vdso64/note.S b/arch/ppc64/kernel/vdso64/note.S
new file mode 100644
index 0000000..dc2a509
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/note.S
@@ -0,0 +1 @@
+#include "../vdso32/note.S"
diff --git a/arch/ppc64/kernel/vdso64/vdso64.lds.S b/arch/ppc64/kernel/vdso64/vdso64.lds.S
index 942c815..9cb2818 100644
--- a/arch/ppc64/kernel/vdso64/vdso64.lds.S
+++ b/arch/ppc64/kernel/vdso64/vdso64.lds.S
@@ -18,12 +18,14 @@
   .gnu.version_d  : { *(.gnu.version_d) }
   .gnu.version_r  : { *(.gnu.version_r) }
 
+  .note		  : { *(.note.*) }		:text	:note
+
   . = ALIGN (16);
   .text           :
   {
     *(.text .stub .text.* .gnu.linkonce.t.*)
     *(.sfpr .glink)
-  }
+  }						:text
   PROVIDE (__etext = .);
   PROVIDE (_etext = .);
   PROVIDE (etext = .);
@@ -88,6 +90,7 @@
 PHDRS
 {
   text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  note PT_NOTE FLAGS(4); /* PF_R */
   dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
   eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
 }
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index eedd1d3..879f39b 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -432,6 +432,7 @@
 {
 	ops->qirr_info(cpu, IPI_PRIORITY);
 }
+#endif /* CONFIG_SMP */
 
 void xics_setup_cpu(void)
 {
@@ -439,9 +440,17 @@
 
 	ops->cppr_info(cpu, 0xff);
 	iosync();
-}
 
-#endif /* CONFIG_SMP */
+	/*
+	 * Put the calling processor into the GIQ.  This is really only
+	 * necessary from a secondary thread as the OF start-cpu interface
+	 * performs this function for us on primary threads.
+	 *
+	 * XXX: undo of teardown on kexec needs this too, as may hotplug
+	 */
+	rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+		(1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
+}
 
 void xics_init_IRQ(void)
 {
@@ -563,8 +572,7 @@
 	for (; i < NR_IRQS; ++i)
 		get_irq_desc(i)->handler = &xics_pic;
 
-	ops->cppr_info(boot_cpuid, 0xff);
-	iosync();
+	xics_setup_cpu();
 
 	ppc64_boot_msg(0x21, "XICS Done");
 }
diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
index 8c0156a..c23d469 100644
--- a/arch/ppc64/mm/hash_low.S
+++ b/arch/ppc64/mm/hash_low.S
@@ -85,7 +85,10 @@
 	bne-	htab_wrong_access
 	/* Check if PTE is busy */
 	andi.	r0,r31,_PAGE_BUSY
-	bne-	1b
+	/* If so, just bail out and refault if needed. Someone else
+	 * is changing this PTE anyway and might hash it.
+	 */
+	bne-	bail_ok
 	/* Prepare new PTE value (turn access RW into DIRTY, then
 	 * add BUSY,HASHPTE and ACCESSED)
 	 */
@@ -215,6 +218,10 @@
 	/* Try all again */
 	b	htab_insert_pte	
 
+bail_ok:
+	li	r3,0
+	b	bail
+
 htab_pte_insert_ok:
 	/* Insert slot number & secondary bit in PTE */
 	rldimi	r30,r3,12,63-15
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index 144657e..52b6b93 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -320,8 +320,7 @@
 
 	j = 0;
 	for (i = 0; i < number; i++) {
-		if ((batch->addr[i] >= USER_START) &&
-		    (batch->addr[i] <= USER_END))
+		if (batch->addr[i] < KERNELBASE)
 			vsid = get_vsid(context, batch->addr[i]);
 		else
 			vsid = get_kernel_vsid(batch->addr[i]);
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index e48be12..0a0f970 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -298,24 +298,23 @@
 	int local = 0;
 	cpumask_t tmp;
 
+	if ((ea & ~REGION_MASK) > EADDR_MASK)
+		return 1;
+
  	switch (REGION_ID(ea)) {
 	case USER_REGION_ID:
 		user_region = 1;
 		mm = current->mm;
-		if ((ea > USER_END) || (! mm))
+		if (! mm)
 			return 1;
 
 		vsid = get_vsid(mm->context.id, ea);
 		break;
 	case IO_REGION_ID:
-		if (ea > IMALLOC_END)
-			return 1;
 		mm = &ioremap_mm;
 		vsid = get_kernel_vsid(ea);
 		break;
 	case VMALLOC_REGION_ID:
-		if (ea > VMALLOC_END)
-			return 1;
 		mm = &init_mm;
 		vsid = get_kernel_vsid(ea);
 		break;
@@ -362,7 +361,7 @@
 	unsigned long vsid, vpn, va, hash, secondary, slot;
 	unsigned long huge = pte_huge(pte);
 
-	if ((ea >= USER_START) && (ea <= USER_END))
+	if (ea < KERNELBASE)
 		vsid = get_vsid(context, ea);
 	else
 		vsid = get_kernel_vsid(ea);
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index 390296e..d3bf86a 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -42,7 +42,7 @@
 	return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
 }
 
-static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
+static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
 {
 	int index;
 
@@ -52,21 +52,21 @@
 
 	index = hugepgd_index(addr);
 	BUG_ON(index >= PTRS_PER_HUGEPGD);
-	return mm->context.huge_pgdir + index;
+	return (pud_t *)(mm->context.huge_pgdir + index);
 }
 
-static inline pte_t *hugepte_offset(pgd_t *dir, unsigned long addr)
+static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr)
 {
 	int index;
 
-	if (pgd_none(*dir))
+	if (pud_none(*dir))
 		return NULL;
 
 	index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
-	return (pte_t *)pgd_page(*dir) + index;
+	return (pte_t *)pud_page(*dir) + index;
 }
 
-static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
+static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
 {
 	BUG_ON(! in_hugepage_area(mm->context, addr));
 
@@ -90,10 +90,9 @@
 	return hugepgd_offset(mm, addr);
 }
 
-static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir,
-			    unsigned long addr)
+static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr)
 {
-	if (! pgd_present(*dir)) {
+	if (! pud_present(*dir)) {
 		pte_t *new;
 
 		spin_unlock(&mm->page_table_lock);
@@ -104,7 +103,7 @@
 		 * Because we dropped the lock, we should re-check the
 		 * entry, as somebody else could have populated it..
 		 */
-		if (pgd_present(*dir)) {
+		if (pud_present(*dir)) {
 			if (new)
 				kmem_cache_free(zero_cache, new);
 		} else {
@@ -115,7 +114,7 @@
 			ptepage = virt_to_page(new);
 			ptepage->mapping = (void *) mm;
 			ptepage->index = addr & HUGEPGDIR_MASK;
-			pgd_populate(mm, dir, new);
+			pud_populate(mm, dir, new);
 		}
 	}
 
@@ -124,28 +123,28 @@
 
 static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
-	pgd_t *pgd;
+	pud_t *pud;
 
 	BUG_ON(! in_hugepage_area(mm->context, addr));
 
-	pgd = hugepgd_offset(mm, addr);
-	if (! pgd)
+	pud = hugepgd_offset(mm, addr);
+	if (! pud)
 		return NULL;
 
-	return hugepte_offset(pgd, addr);
+	return hugepte_offset(pud, addr);
 }
 
 static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
-	pgd_t *pgd;
+	pud_t *pud;
 
 	BUG_ON(! in_hugepage_area(mm->context, addr));
 
-	pgd = hugepgd_alloc(mm, addr);
-	if (! pgd)
+	pud = hugepgd_alloc(mm, addr);
+	if (! pud)
 		return NULL;
 
-	return hugepte_alloc(mm, pgd, addr);
+	return hugepte_alloc(mm, pud, addr);
 }
 
 static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -709,10 +708,10 @@
 
 	/* cleanup any hugepte pages leftover */
 	for (i = 0; i < PTRS_PER_HUGEPGD; i++) {
-		pgd_t *pgd = pgdir + i;
+		pud_t *pud = (pud_t *)(pgdir + i);
 
-		if (! pgd_none(*pgd)) {
-			pte_t *pte = (pte_t *)pgd_page(*pgd);
+		if (! pud_none(*pud)) {
+			pte_t *pte = (pte_t *)pud_page(*pud);
 			struct page *ptepage = virt_to_page(pte);
 
 			ptepage->mapping = NULL;
@@ -720,7 +719,7 @@
 			BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE));
 			kmem_cache_free(zero_cache, pte);
 		}
-		pgd_clear(pgd);
+		pud_clear(pud);
 	}
 
 	BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE));
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index 9d92b0d..cb8727f 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -14,6 +14,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/semaphore.h>
+#include <asm/imalloc.h>
 
 static DECLARE_MUTEX(imlist_sem);
 struct vm_struct * imlist = NULL;
@@ -23,11 +24,11 @@
 	unsigned long addr;
 	struct vm_struct **p, *tmp;
 
-	addr = IMALLOC_START;
+	addr = ioremap_bot;
 	for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
 		if (size + addr < (unsigned long) tmp->addr)
 			break;
-		if ((unsigned long)tmp->addr >= IMALLOC_START) 
+		if ((unsigned long)tmp->addr >= ioremap_bot)
 			addr = tmp->size + (unsigned long) tmp->addr;
 		if (addr > IMALLOC_END-size) 
 			return 1;
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index a7149b9..4b42aff 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -64,6 +64,7 @@
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 #include <asm/vdso.h>
+#include <asm/imalloc.h>
 
 int mem_init_done;
 unsigned long ioremap_bot = IMALLOC_BASE;
@@ -136,14 +137,78 @@
 
 #else
 
+static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
+				  unsigned long end)
+{
+	pte_t *pte;
+
+	pte = pte_offset_kernel(pmd, addr);
+	do {
+		pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
+		WARN_ON(!pte_none(ptent) && !pte_present(ptent));
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
+				     unsigned long end)
+{
+	pmd_t *pmd;
+	unsigned long next;
+
+	pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+		if (pmd_none_or_clear_bad(pmd))
+			continue;
+		unmap_im_area_pte(pmd, addr, next);
+	} while (pmd++, addr = next, addr != end);
+}
+
+static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
+				     unsigned long end)
+{
+	pud_t *pud;
+	unsigned long next;
+
+	pud = pud_offset(pgd, addr);
+	do {
+		next = pud_addr_end(addr, end);
+		if (pud_none_or_clear_bad(pud))
+			continue;
+		unmap_im_area_pmd(pud, addr, next);
+	} while (pud++, addr = next, addr != end);
+}
+
+static void unmap_im_area(unsigned long addr, unsigned long end)
+{
+	struct mm_struct *mm = &ioremap_mm;
+	unsigned long next;
+	pgd_t *pgd;
+
+	spin_lock(&mm->page_table_lock);
+
+	pgd = pgd_offset_i(addr);
+	flush_cache_vunmap(addr, end);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (pgd_none_or_clear_bad(pgd))
+			continue;
+		unmap_im_area_pud(pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+	flush_tlb_kernel_range(start, end);
+
+	spin_unlock(&mm->page_table_lock);
+}
+
 /*
  * map_io_page currently only called by __ioremap
  * map_io_page adds an entry to the ioremap page table
  * and adds an entry to the HPT, possibly bolting it
  */
-static void map_io_page(unsigned long ea, unsigned long pa, int flags)
+static int map_io_page(unsigned long ea, unsigned long pa, int flags)
 {
 	pgd_t *pgdp;
+	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
 	unsigned long vsid;
@@ -151,9 +216,15 @@
 	if (mem_init_done) {
 		spin_lock(&ioremap_mm.page_table_lock);
 		pgdp = pgd_offset_i(ea);
-		pmdp = pmd_alloc(&ioremap_mm, pgdp, ea);
+		pudp = pud_alloc(&ioremap_mm, pgdp, ea);
+		if (!pudp)
+			return -ENOMEM;
+		pmdp = pmd_alloc(&ioremap_mm, pudp, ea);
+		if (!pmdp)
+			return -ENOMEM;
 		ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
-
+		if (!ptep)
+			return -ENOMEM;
 		pa = abs_to_phys(pa);
 		set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
 							  __pgprot(flags)));
@@ -181,6 +252,7 @@
 			panic("map_io_page: could not insert mapping");
 		}
 	}
+	return 0;
 }
 
 
@@ -194,9 +266,14 @@
 		flags |= pgprot_val(PAGE_KERNEL);
 
 	for (i = 0; i < size; i += PAGE_SIZE)
-		map_io_page(ea+i, pa+i, flags);
+		if (map_io_page(ea+i, pa+i, flags))
+			goto failure;
 
 	return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+ failure:
+	if (mem_init_done)
+		unmap_im_area(ea, ea + size);
+	return NULL;
 }
 
 
@@ -206,10 +283,11 @@
 	return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
 }
 
-void __iomem *
-__ioremap(unsigned long addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long addr, unsigned long size,
+			 unsigned long flags)
 {
 	unsigned long pa, ea;
+	void __iomem *ret;
 
 	/*
 	 * Choose an address to map it to.
@@ -232,12 +310,16 @@
 		if (area == NULL)
 			return NULL;
 		ea = (unsigned long)(area->addr);
+		ret = __ioremap_com(addr, pa, ea, size, flags);
+		if (!ret)
+			im_free(area->addr);
 	} else {
 		ea = ioremap_bot;
-		ioremap_bot += size;
+		ret = __ioremap_com(addr, pa, ea, size, flags);
+		if (ret)
+			ioremap_bot += size;
 	}
-
-	return __ioremap_com(addr, pa, ea, size, flags);
+	return ret;
 }
 
 #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
@@ -246,6 +328,7 @@
 		       unsigned long size, unsigned long flags)
 {
 	struct vm_struct *area;
+	void __iomem *ret;
 	
 	/* For now, require page-aligned values for pa, ea, and size */
 	if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
@@ -276,7 +359,12 @@
 		}
 	}
 	
-	if (__ioremap_com(pa, pa, ea, size, flags) != (void *) ea) {
+	ret = __ioremap_com(pa, pa, ea, size, flags);
+	if (ret == NULL) {
+		printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
+		return 1;
+	}
+	if (ret != (void *) ea) {
 		printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
 		return 1;
 	}
@@ -284,69 +372,6 @@
 	return 0;
 }
 
-static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
-				  unsigned long size)
-{
-	unsigned long base, end;
-	pte_t *pte;
-
-	if (pmd_none(*pmd))
-		return;
-	if (pmd_bad(*pmd)) {
-		pmd_ERROR(*pmd);
-		pmd_clear(pmd);
-		return;
-	}
-
-	pte = pte_offset_kernel(pmd, address);
-	base = address & PMD_MASK;
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-
-	do {
-		pte_t page;
-		page = ptep_get_and_clear(&ioremap_mm, base + address, pte);
-		address += PAGE_SIZE;
-		pte++;
-		if (pte_none(page))
-			continue;
-		if (pte_present(page))
-			continue;
-		printk(KERN_CRIT "Whee.. Swapped out page in kernel page"
-		       " table\n");
-	} while (address < end);
-}
-
-static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
-				  unsigned long size)
-{
-	unsigned long base, end;
-	pmd_t *pmd;
-
-	if (pgd_none(*dir))
-		return;
-	if (pgd_bad(*dir)) {
-		pgd_ERROR(*dir);
-		pgd_clear(dir);
-		return;
-	}
-
-	pmd = pmd_offset(dir, address);
-	base = address & PGDIR_MASK;
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-
-	do {
-		unmap_im_area_pte(pmd, base + address, end - address);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-}
-
 /*  
  * Unmap an IO region and remove it from imalloc'd list.
  * Access to IO memory should be serialized by driver.
@@ -356,39 +381,19 @@
  */
 void iounmap(volatile void __iomem *token)
 {
-	unsigned long address, start, end, size;
-	struct mm_struct *mm;
-	pgd_t *dir;
+	unsigned long address, size;
 	void *addr;
 
-	if (!mem_init_done) {
+	if (!mem_init_done)
 		return;
-	}
 	
 	addr = (void *) ((unsigned long __force) token & PAGE_MASK);
 	
-	if ((size = im_free(addr)) == 0) {
+	if ((size = im_free(addr)) == 0)
 		return;
-	}
 
 	address = (unsigned long)addr; 
-	start = address;
-	end = address + size;
-
-	mm = &ioremap_mm;
-	spin_lock(&mm->page_table_lock);
-
-	dir = pgd_offset_i(address);
-	flush_cache_vunmap(address, end);
-	do {
-		unmap_im_area_pmd(dir, address, end - address);
-		address = (address + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	} while (address && (address < end));
-	flush_tlb_kernel_range(start, end);
-
-	spin_unlock(&mm->page_table_lock);
-	return;
+	unmap_im_area(address, address + size);
 }
 
 static int iounmap_subset_regions(unsigned long addr, unsigned long size)
@@ -664,7 +669,7 @@
 	zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 	zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
 
-	free_area_init_node(0, &contig_page_data, zones_size,
+	free_area_init_node(0, NODE_DATA(0), zones_size,
 			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 }
 #endif /* CONFIG_DISCONTIGMEM */
diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
index 6a20773..244150a 100644
--- a/arch/ppc64/mm/slb.c
+++ b/arch/ppc64/mm/slb.c
@@ -33,8 +33,8 @@
 	return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
 }
 
-static inline void create_slbe(unsigned long ea, unsigned long vsid,
-			       unsigned long flags, unsigned long entry)
+static inline void create_slbe(unsigned long ea, unsigned long flags,
+			       unsigned long entry)
 {
 	asm volatile("slbmte  %0,%1" :
 		     : "r" (mk_vsid_data(ea, flags)),
@@ -145,9 +145,8 @@
  	asm volatile("isync":::"memory");
  	asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
 	asm volatile("isync; slbia; isync":::"memory");
-	create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0);
-	create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE),
-		    SLB_VSID_KERNEL, 1);
+	create_slbe(KERNELBASE, flags, 0);
+	create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1);
 	/* We don't bolt the stack for the time being - we're in boot,
 	 * so the stack is in the bolted segment.  By the time it goes
 	 * elsewhere, we'll call _switch() which will bolt in the new
diff --git a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
index 3149113..df4bbe1 100644
--- a/arch/ppc64/mm/stab.c
+++ b/arch/ppc64/mm/stab.c
@@ -19,6 +19,11 @@
 #include <asm/paca.h>
 #include <asm/cputable.h>
 
+struct stab_entry {
+	unsigned long esid_data;
+	unsigned long vsid_data;
+};
+
 /* Both the segment table and SLB code uses the following cache */
 #define NR_STAB_CACHE_ENTRIES 8
 DEFINE_PER_CPU(long, stab_cache_ptr);
diff --git a/arch/ppc64/xmon/ppc-opc.c b/arch/ppc64/xmon/ppc-opc.c
index 1e4e7e3..5ee8fc3 100644
--- a/arch/ppc64/xmon/ppc-opc.c
+++ b/arch/ppc64/xmon/ppc-opc.c
@@ -20,6 +20,7 @@
    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.  */
 
+#include <linux/stddef.h>
 #include "nonstdio.h"
 #include "ppc.h"
 
@@ -110,12 +111,12 @@
   /* The zero index is used to indicate the end of the list of
      operands.  */
 #define UNUSED 0
-  { 0, 0, 0, 0, 0 },
+  { 0, 0, NULL, NULL, 0 },
 
   /* The BA field in an XL form instruction.  */
 #define BA UNUSED + 1
 #define BA_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_CR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BA field in an XL form instruction when it must be the same
      as the BT field in the same instruction.  */
@@ -125,7 +126,7 @@
   /* The BB field in an XL form instruction.  */
 #define BB BAT + 1
 #define BB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_CR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BB field in an XL form instruction when it must be the same
      as the BA field in the same instruction.  */
@@ -168,21 +169,21 @@
 
   /* The BF field in an X or XL form instruction.  */
 #define BF BDPA + 1
-  { 3, 23, 0, 0, PPC_OPERAND_CR },
+  { 3, 23, NULL, NULL, PPC_OPERAND_CR },
 
   /* An optional BF field.  This is used for comparison instructions,
      in which an omitted BF field is taken as zero.  */
 #define OBF BF + 1
-  { 3, 23, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+  { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
 
   /* The BFA field in an X or XL form instruction.  */
 #define BFA OBF + 1
-  { 3, 18, 0, 0, PPC_OPERAND_CR },
+  { 3, 18, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BI field in a B form or XL form instruction.  */
 #define BI BFA + 1
 #define BI_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_CR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BO field in a B form instruction.  Certain values are
      illegal.  */
@@ -197,36 +198,36 @@
 
   /* The BT field in an X or XL form instruction.  */
 #define BT BOE + 1
-  { 5, 21, 0, 0, PPC_OPERAND_CR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_CR },
 
   /* The condition register number portion of the BI field in a B form
      or XL form instruction.  This is used for the extended
      conditional branch mnemonics, which set the lower two bits of the
      BI field.  This field is optional.  */
 #define CR BT + 1
-  { 3, 18, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+  { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
 
   /* The CRB field in an X form instruction.  */
 #define CRB CR + 1
-  { 5, 6, 0, 0, 0 },
+  { 5, 6, NULL, NULL, 0 },
 
   /* The CRFD field in an X form instruction.  */
 #define CRFD CRB + 1
-  { 3, 23, 0, 0, PPC_OPERAND_CR },
+  { 3, 23, NULL, NULL, PPC_OPERAND_CR },
 
   /* The CRFS field in an X form instruction.  */
 #define CRFS CRFD + 1
-  { 3, 0, 0, 0, PPC_OPERAND_CR },
+  { 3, 0, NULL, NULL, PPC_OPERAND_CR },
 
   /* The CT field in an X form instruction.  */
 #define CT CRFS + 1
-  { 5, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
   /* The D field in a D form instruction.  This is a displacement off
      a register, and implies that the next operand is a register in
      parentheses.  */
 #define D CT + 1
-  { 16, 0, 0, 0, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+  { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
 
   /* The DE field in a DE form instruction.  This is like D, but is 12
      bits only.  */
@@ -252,40 +253,40 @@
 
   /* The E field in a wrteei instruction.  */
 #define E DS + 1
-  { 1, 15, 0, 0, 0 },
+  { 1, 15, NULL, NULL, 0 },
 
   /* The FL1 field in a POWER SC form instruction.  */
 #define FL1 E + 1
-  { 4, 12, 0, 0, 0 },
+  { 4, 12, NULL, NULL, 0 },
 
   /* The FL2 field in a POWER SC form instruction.  */
 #define FL2 FL1 + 1
-  { 3, 2, 0, 0, 0 },
+  { 3, 2, NULL, NULL, 0 },
 
   /* The FLM field in an XFL form instruction.  */
 #define FLM FL2 + 1
-  { 8, 17, 0, 0, 0 },
+  { 8, 17, NULL, NULL, 0 },
 
   /* The FRA field in an X or A form instruction.  */
 #define FRA FLM + 1
 #define FRA_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_FPR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FRB field in an X or A form instruction.  */
 #define FRB FRA + 1
 #define FRB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_FPR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FRC field in an A form instruction.  */
 #define FRC FRB + 1
 #define FRC_MASK (0x1f << 6)
-  { 5, 6, 0, 0, PPC_OPERAND_FPR },
+  { 5, 6, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FRS field in an X form instruction or the FRT field in a D, X
      or A form instruction.  */
 #define FRS FRC + 1
 #define FRT FRS
-  { 5, 21, 0, 0, PPC_OPERAND_FPR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FXM field in an XFX instruction.  */
 #define FXM FRS + 1
@@ -298,11 +299,11 @@
 
   /* The L field in a D or X form instruction.  */
 #define L FXM4 + 1
-  { 1, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
   /* The LEV field in a POWER SC form instruction.  */
 #define LEV L + 1
-  { 7, 5, 0, 0, 0 },
+  { 7, 5, NULL, NULL, 0 },
 
   /* The LI field in an I form instruction.  The lower two bits are
      forced to zero.  */
@@ -316,24 +317,24 @@
 
   /* The LS field in an X (sync) form instruction.  */
 #define LS LIA + 1
-  { 2, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
   /* The MB field in an M form instruction.  */
 #define MB LS + 1
 #define MB_MASK (0x1f << 6)
-  { 5, 6, 0, 0, 0 },
+  { 5, 6, NULL, NULL, 0 },
 
   /* The ME field in an M form instruction.  */
 #define ME MB + 1
 #define ME_MASK (0x1f << 1)
-  { 5, 1, 0, 0, 0 },
+  { 5, 1, NULL, NULL, 0 },
 
   /* The MB and ME fields in an M form instruction expressed a single
      operand which is a bitmask indicating which bits to select.  This
      is a two operand form using PPC_OPERAND_NEXT.  See the
      description in opcode/ppc.h for what this means.  */
 #define MBE ME + 1
-  { 5, 6, 0, 0, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+  { 5, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
   { 32, 0, insert_mbe, extract_mbe, 0 },
 
   /* The MB or ME field in an MD or MDS form instruction.  The high
@@ -345,7 +346,7 @@
 
   /* The MO field in an mbar instruction.  */
 #define MO MB6 + 1
-  { 5, 21, 0, 0, 0 },
+  { 5, 21, NULL, NULL, 0 },
 
   /* The NB field in an X form instruction.  The value 32 is stored as
      0.  */
@@ -361,34 +362,34 @@
   /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction.  */
 #define RA NSI + 1
 #define RA_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_GPR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in the DQ form lq instruction, which has special
      value restrictions.  */
 #define RAQ RA + 1
-  { 5, 16, insert_raq, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in a D or X form instruction which is an updating
      load, which means that the RA field may not be zero and may not
      equal the RT field.  */
 #define RAL RAQ + 1
-  { 5, 16, insert_ral, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in an lmw instruction, which has special value
      restrictions.  */
 #define RAM RAL + 1
-  { 5, 16, insert_ram, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in a D or X form instruction which is an updating
      store or an updating floating point load, which means that the RA
      field may not be zero.  */
 #define RAS RAM + 1
-  { 5, 16, insert_ras, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR },
 
   /* The RB field in an X, XO, M, or MDS form instruction.  */
 #define RB RAS + 1
 #define RB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_GPR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
 
   /* The RB field in an X form instruction when it must be the same as
      the RS field in the instruction.  This is used for extended
@@ -402,22 +403,22 @@
 #define RS RBS + 1
 #define RT RS
 #define RT_MASK (0x1f << 21)
-  { 5, 21, 0, 0, PPC_OPERAND_GPR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_GPR },
 
   /* The RS field of the DS form stq instruction, which has special
      value restrictions.  */
 #define RSQ RS + 1
-  { 5, 21, insert_rsq, 0, PPC_OPERAND_GPR },
+  { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR },
 
   /* The RT field of the DQ form lq instruction, which has special
      value restrictions.  */
 #define RTQ RSQ + 1
-  { 5, 21, insert_rtq, 0, PPC_OPERAND_GPR },
+  { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR },
 
   /* The SH field in an X or M form instruction.  */
 #define SH RTQ + 1
 #define SH_MASK (0x1f << 11)
-  { 5, 11, 0, 0, 0 },
+  { 5, 11, NULL, NULL, 0 },
 
   /* The SH field in an MD form instruction.  This is split.  */
 #define SH6 SH + 1
@@ -426,12 +427,12 @@
 
   /* The SI field in a D form instruction.  */
 #define SI SH6 + 1
-  { 16, 0, 0, 0, PPC_OPERAND_SIGNED },
+  { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
 
   /* The SI field in a D form instruction when we accept a wide range
      of positive values.  */
 #define SISIGNOPT SI + 1
-  { 16, 0, 0, 0, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+  { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
 
   /* The SPR field in an XFX form instruction.  This is flipped--the
      lower 5 bits are stored in the upper 5 and vice- versa.  */
@@ -443,25 +444,25 @@
   /* The BAT index number in an XFX form m[ft]ibat[lu] instruction.  */
 #define SPRBAT SPR + 1
 #define SPRBAT_MASK (0x3 << 17)
-  { 2, 17, 0, 0, 0 },
+  { 2, 17, NULL, NULL, 0 },
 
   /* The SPRG register number in an XFX form m[ft]sprg instruction.  */
 #define SPRG SPRBAT + 1
 #define SPRG_MASK (0x3 << 16)
-  { 2, 16, 0, 0, 0 },
+  { 2, 16, NULL, NULL, 0 },
 
   /* The SR field in an X form instruction.  */
 #define SR SPRG + 1
-  { 4, 16, 0, 0, 0 },
+  { 4, 16, NULL, NULL, 0 },
 
   /* The STRM field in an X AltiVec form instruction.  */
 #define STRM SR + 1
 #define STRM_MASK (0x3 << 21)
-  { 2, 21, 0, 0, 0 },
+  { 2, 21, NULL, NULL, 0 },
 
   /* The SV field in a POWER SC form instruction.  */
 #define SV STRM + 1
-  { 14, 2, 0, 0, 0 },
+  { 14, 2, NULL, NULL, 0 },
 
   /* The TBR field in an XFX form instruction.  This is like the SPR
      field, but it is optional.  */
@@ -471,52 +472,52 @@
   /* The TO field in a D or X form instruction.  */
 #define TO TBR + 1
 #define TO_MASK (0x1f << 21)
-  { 5, 21, 0, 0, 0 },
+  { 5, 21, NULL, NULL, 0 },
 
   /* The U field in an X form instruction.  */
 #define U TO + 1
-  { 4, 12, 0, 0, 0 },
+  { 4, 12, NULL, NULL, 0 },
 
   /* The UI field in a D form instruction.  */
 #define UI U + 1
-  { 16, 0, 0, 0, 0 },
+  { 16, 0, NULL, NULL, 0 },
 
   /* The VA field in a VA, VX or VXR form instruction.  */
 #define VA UI + 1
 #define VA_MASK	(0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_VR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_VR },
 
   /* The VB field in a VA, VX or VXR form instruction.  */
 #define VB VA + 1
 #define VB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_VR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_VR },
 
   /* The VC field in a VA form instruction.  */
 #define VC VB + 1
 #define VC_MASK (0x1f << 6)
-  { 5, 6, 0, 0, PPC_OPERAND_VR },
+  { 5, 6, NULL, NULL, PPC_OPERAND_VR },
 
   /* The VD or VS field in a VA, VX, VXR or X form instruction.  */
 #define VD VC + 1
 #define VS VD
 #define VD_MASK (0x1f << 21)
-  { 5, 21, 0, 0, PPC_OPERAND_VR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_VR },
 
   /* The SIMM field in a VX form instruction.  */
 #define SIMM VD + 1
-  { 5, 16, 0, 0, PPC_OPERAND_SIGNED},
+  { 5, 16, NULL, NULL, PPC_OPERAND_SIGNED},
 
   /* The UIMM field in a VX form instruction.  */
 #define UIMM SIMM + 1
-  { 5, 16, 0, 0, 0 },
+  { 5, 16, NULL, NULL, 0 },
 
   /* The SHB field in a VA form instruction.  */
 #define SHB UIMM + 1
-  { 4, 6, 0, 0, 0 },
+  { 4, 6, NULL, NULL, 0 },
 
   /* The other UIMM field in a EVX form instruction.  */
 #define EVUIMM SHB + 1
-  { 5, 11, 0, 0, 0 },
+  { 5, 11, NULL, NULL, 0 },
 
   /* The other UIMM field in a half word EVX form instruction.  */
 #define EVUIMM_2 EVUIMM + 1
@@ -533,11 +534,11 @@
   /* The WS field.  */
 #define WS EVUIMM_8 + 1
 #define WS_MASK (0x7 << 11)
-  { 3, 11, 0, 0, 0 },
+  { 3, 11, NULL, NULL, 0 },
 
   /* The L field in an mtmsrd instruction */
 #define MTMSRD_L WS + 1
-  { 1, 16, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
 };
 
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 1358b42..07fd041 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Wed Mar  2 16:57:55 2005
+# Linux kernel version: 2.6.12-rc3
+# Fri Apr 22 15:30:58 2005
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -15,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -26,24 +27,25 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -261,7 +263,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
@@ -329,6 +330,7 @@
 CONFIG_NET_QOS=y
 CONFIG_NET_ESTIMATOR=y
 CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
 CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_ROUTE=y
@@ -338,6 +340,7 @@
 # CONFIG_NET_CLS_IND is not set
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
 # CONFIG_NET_CLS_ACT is not set
 CONFIG_NET_CLS_POLICE=y
 
@@ -393,6 +396,8 @@
 CONFIG_IUCV=m
 # CONFIG_NETIUCV is not set
 # CONFIG_SMSGIUCV is not set
+# CONFIG_CLAW is not set
+# CONFIG_MPC is not set
 CONFIG_QETH=y
 
 #
@@ -532,10 +537,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
@@ -560,6 +568,7 @@
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_DES_Z990 is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
index 96571ff..03d03c6 100644
--- a/arch/s390/kernel/compat_ioctl.c
+++ b/arch/s390/kernel/compat_ioctl.c
@@ -16,6 +16,7 @@
 #define CODE
 #include "../../../fs/compat_ioctl.c"
 #include <asm/dasd.h>
+#include <asm/cmb.h>
 #include <asm/tape390.h>
 
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
@@ -58,7 +59,11 @@
 COMPATIBLE_IOCTL(BIODASDPSRD)
 COMPATIBLE_IOCTL(BIODASDGATTR)
 COMPATIBLE_IOCTL(BIODASDSATTR)
-
+#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE)
+COMPATIBLE_IOCTL(BIODASDCMFENABLE)
+COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
+COMPATIBLE_IOCTL(BIODASDREADALLCMB)
+#endif
 #endif
 
 #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE)
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 647233c..2688936 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -32,6 +32,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/signal.h>
 
 #include <asm/segment.h>
 #include <asm/page.h>
@@ -609,7 +610,7 @@
 		/* continue and stop at next (return from) syscall */
 	case PTRACE_CONT:
 		/* restart after signal. */
-		if ((unsigned long) data >= _NSIG)
+		if (!valid_signal(data))
 			return -EIO;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -637,7 +638,7 @@
 
 	case PTRACE_SINGLESTEP:
 		/* set the trap flag. */
-		if ((unsigned long) data >= _NSIG)
+		if (!valid_signal(data))
 			return -EIO;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		child->exit_code = data;
@@ -711,18 +712,13 @@
 asmlinkage void
 syscall_trace(struct pt_regs *regs, int entryexit)
 {
-	if (unlikely(current->audit_context)) {
-		if (!entryexit)
-			audit_syscall_entry(current, regs->gprs[2],
-					    regs->orig_gpr2, regs->gprs[3],
-					    regs->gprs[4], regs->gprs[5]);
-		else
-			audit_syscall_exit(current, regs->gprs[2]);
-	}
+	if (unlikely(current->audit_context) && entryexit)
+		audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
+		goto out;
 	if (!(current->ptrace & PT_PTRACED))
-		return;
+		goto out;
 	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
 				 ? 0x80 : 0));
 
@@ -735,4 +731,10 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
+ out:
+	if (unlikely(current->audit_context) && !entryexit)
+		audit_syscall_entry(current, 
+				    test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
+				    regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
+				    regs->gprs[4], regs->gprs[5]);
 }
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 11fd6d5..bee654a 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -34,7 +34,6 @@
 EXPORT_SYMBOL(__strncpy_from_user_asm);
 EXPORT_SYMBOL(__strnlen_user_asm);
 EXPORT_SYMBOL(diag10);
-EXPORT_SYMBOL(default_storage_key);
 
 /*
  * semaphore ops
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index c879c40..df83215 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -44,6 +44,8 @@
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
 #include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
 
 /*
  * Machine setup..
@@ -53,13 +55,14 @@
 unsigned int console_irq = -1;
 unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
-unsigned int default_storage_key = 0;
 struct {
 	unsigned long addr, size, type;
 } memory_chunk[MEMORY_CHUNKS] = { { 0 } };
 #define CHUNK_READ_WRITE 0
 #define CHUNK_READ_ONLY 1
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
+unsigned long __initdata zholes_size[MAX_NR_ZONES];
+static unsigned long __initdata memory_end;
 
 /*
  * Setup options
@@ -78,11 +81,15 @@
 
 static struct resource code_resource = {
 	.name  = "Kernel code",
+	.start = (unsigned long) &_text,
+	.end = (unsigned long) &_etext - 1,
 	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
 static struct resource data_resource = {
 	.name = "Kernel data",
+	.start = (unsigned long) &_etext,
+	.end = (unsigned long) &_edata - 1,
 	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
@@ -310,90 +317,50 @@
 
 EXPORT_SYMBOL(machine_power_off);
 
-/*
- * Setup function called from init/main.c just after the banner
- * was printed.
- */
-extern char _pstart, _pend, _stext;
-
-void __init setup_arch(char **cmdline_p)
+static void __init
+add_memory_hole(unsigned long start, unsigned long end)
 {
-        unsigned long bootmap_size;
-        unsigned long memory_start, memory_end;
-        char c = ' ', cn, *to = command_line, *from = COMMAND_LINE;
-	unsigned long start_pfn, end_pfn;
-        static unsigned int smptrap=0;
-        unsigned long delay = 0;
-	struct _lowcore *lc;
-	int i;
+	unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
 
-        if (smptrap)
-                return;
-        smptrap=1;
+	if (end <= dma_pfn)
+		zholes_size[ZONE_DMA] += end - start + 1;
+	else if (start > dma_pfn)
+		zholes_size[ZONE_NORMAL] += end - start + 1;
+	else {
+		zholes_size[ZONE_DMA] += dma_pfn - start + 1;
+		zholes_size[ZONE_NORMAL] += end - dma_pfn;
+	}
+}
 
-        /*
-         * print what head.S has found out about the machine 
-         */
-#ifndef CONFIG_ARCH_S390X
-	printk((MACHINE_IS_VM) ?
-	       "We are running under VM (31 bit mode)\n" :
-	       "We are running native (31 bit mode)\n");
-	printk((MACHINE_HAS_IEEE) ?
-	       "This machine has an IEEE fpu\n" :
-	       "This machine has no IEEE fpu\n");
-#else /* CONFIG_ARCH_S390X */
-	printk((MACHINE_IS_VM) ?
-	       "We are running under VM (64 bit mode)\n" :
-	       "We are running native (64 bit mode)\n");
-#endif /* CONFIG_ARCH_S390X */
+static void __init
+parse_cmdline_early(char **cmdline_p)
+{
+	char c = ' ', cn, *to = command_line, *from = COMMAND_LINE;
+	unsigned long delay = 0;
 
-        ROOT_DEV = Root_RAM0;
-        memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
-#ifndef CONFIG_ARCH_S390X
-	memory_end = memory_size & ~0x400000UL;  /* align memory end to 4MB */
-        /*
-         * We need some free virtual space to be able to do vmalloc.
-         * On a machine with 2GB memory we make sure that we have at
-         * least 128 MB free space for vmalloc.
-         */
-        if (memory_end > 1920*1024*1024)
-                memory_end = 1920*1024*1024;
-#else /* CONFIG_ARCH_S390X */
-	memory_end = memory_size & ~0x200000UL;  /* detected in head.s */
-#endif /* CONFIG_ARCH_S390X */
-        init_mm.start_code = PAGE_OFFSET;
-        init_mm.end_code = (unsigned long) &_etext;
-        init_mm.end_data = (unsigned long) &_edata;
-        init_mm.brk = (unsigned long) &_end;
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
-	code_resource.start = (unsigned long) &_text;
-	code_resource.end = (unsigned long) &_etext - 1;
-	data_resource.start = (unsigned long) &_etext;
-	data_resource.end = (unsigned long) &_edata - 1;
-
-        /* Save unparsed command line copy for /proc/cmdline */
-        memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-        saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
-        for (;;) {
-                /*
-                 * "mem=XXX[kKmM]" sets memsize 
-                 */
-                if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
-                        memory_end = simple_strtoul(from+4, &from, 0);
-                        if ( *from == 'K' || *from == 'k' ) {
-                                memory_end = memory_end << 10;
-                                from++;
-                        } else if ( *from == 'M' || *from == 'm' ) {
-                                memory_end = memory_end << 20;
-                                from++;
-                        }
-                }
-                /*
-                 * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
-                 */
-                if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
-                        delay = simple_strtoul(from+9, &from, 0);
+	for (;;) {
+		/*
+		 * "mem=XXX[kKmM]" sets memsize
+		 */
+		if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
+			memory_end = simple_strtoul(from+4, &from, 0);
+			if ( *from == 'K' || *from == 'k' ) {
+				memory_end = memory_end << 10;
+				from++;
+			} else if ( *from == 'M' || *from == 'm' ) {
+				memory_end = memory_end << 20;
+				from++;
+			}
+		}
+		/*
+		 * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
+		 */
+		if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
+			delay = simple_strtoul(from+9, &from, 0);
 			if (*from == 's' || *from == 'S') {
 				delay = delay*1000000;
 				from++;
@@ -403,116 +370,40 @@
 			}
 			/* now wait for the requested amount of time */
 			udelay(delay);
-                }
-                cn = *(from++);
-                if (!cn)
-                        break;
-                if (cn == '\n')
-                        cn = ' ';  /* replace newlines with space */
+		}
+		cn = *(from++);
+		if (!cn)
+			break;
+		if (cn == '\n')
+			cn = ' ';  /* replace newlines with space */
 		if (cn == 0x0d)
 			cn = ' ';  /* replace 0x0d with space */
-                if (cn == ' ' && c == ' ')
-                        continue;  /* remove additional spaces */
-                c = cn;
-                if (to - command_line >= COMMAND_LINE_SIZE)
-                        break;
-                *(to++) = c;
-        }
-        if (c == ' ' && to > command_line) to--;
-        *to = '\0';
-        *cmdline_p = command_line;
-
-	/*
-	 * partially used pages are not usable - thus
-	 * we are rounding upwards:
-	 */
-	start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	end_pfn = max_pfn = memory_end >> PAGE_SHIFT;
-
-	/*
-	 * Initialize the boot-time allocator (with low memory only):
-	 */
-	bootmap_size = init_bootmem(start_pfn, end_pfn);
-
-	/*
-	 * Register RAM areas with the bootmem allocator.
-	 */
-	for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
-		unsigned long start_chunk, end_chunk;
-
-		if (memory_chunk[i].type != CHUNK_READ_WRITE)
-			continue;
-		start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
-		start_chunk >>= PAGE_SHIFT;
-		end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
-		end_chunk >>= PAGE_SHIFT;
-		if (start_chunk < start_pfn)
-			start_chunk = start_pfn;
-		if (end_chunk > end_pfn)
-			end_chunk = end_pfn;
-		if (start_chunk < end_chunk)
-			free_bootmem(start_chunk << PAGE_SHIFT,
-				     (end_chunk - start_chunk) << PAGE_SHIFT);
-	}
-
-        /*
-         * Reserve the bootmem bitmap itself as well. We do this in two
-         * steps (first step was init_bootmem()) because this catches
-         * the (very unlikely) case of us accidentally initializing the
-         * bootmem allocator with an invalid RAM area.
-         */
-        reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
-
-#ifdef CONFIG_BLK_DEV_INITRD
-        if (INITRD_START) {
-		if (INITRD_START + INITRD_SIZE <= memory_end) {
-			reserve_bootmem(INITRD_START, INITRD_SIZE);
-			initrd_start = INITRD_START;
-			initrd_end = initrd_start + INITRD_SIZE;
-		} else {
-                        printk("initrd extends beyond end of memory "
-                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-                               initrd_start + INITRD_SIZE, memory_end);
-                        initrd_start = initrd_end = 0;
-		}
-        }
-#endif
-
-	for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
-		struct resource *res;
-
-		res = alloc_bootmem_low(sizeof(struct resource));
-		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
-
-		switch (memory_chunk[i].type) {
-		case CHUNK_READ_WRITE:
-			res->name = "System RAM";
+		if (cn == ' ' && c == ' ')
+			continue;  /* remove additional spaces */
+		c = cn;
+		if (to - command_line >= COMMAND_LINE_SIZE)
 			break;
-		case CHUNK_READ_ONLY:
-			res->name = "System ROM";
-			res->flags |= IORESOURCE_READONLY;
-			break;
-		default:
-			res->name = "reserved";
-		}
-		res->start = memory_chunk[i].addr;
-		res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
-		request_resource(&iomem_resource, res);
-		request_resource(res, &code_resource);
-		request_resource(res, &data_resource);
+		*(to++) = c;
 	}
+	if (c == ' ' && to > command_line) to--;
+	*to = '\0';
+	*cmdline_p = command_line;
+}
 
-        /*
-         * Setup lowcore for boot cpu
-         */
-#ifndef CONFIG_ARCH_S390X
-	lc = (struct _lowcore *) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
-	memset(lc, 0, PAGE_SIZE);
-#else /* CONFIG_ARCH_S390X */
-	lc = (struct _lowcore *) __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
-	memset(lc, 0, 2*PAGE_SIZE);
-#endif /* CONFIG_ARCH_S390X */
-	lc->restart_psw.mask = PSW_BASE_BITS;
+static void __init
+setup_lowcore(void)
+{
+	struct _lowcore *lc;
+	int lc_pages;
+
+	/*
+	 * Setup lowcore for boot cpu
+	 */
+	lc_pages = sizeof(void *) == 8 ? 2 : 1;
+	lc = (struct _lowcore *)
+		__alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0);
+	memset(lc, 0, lc_pages * PAGE_SIZE);
+	lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
 	lc->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
 	lc->external_new_psw.mask = PSW_KERNEL_BITS;
@@ -546,6 +437,170 @@
 		lc->diag44_opcode = 0x07000700;
 #endif /* CONFIG_ARCH_S390X */
 	set_prefix((u32)(unsigned long) lc);
+}
+
+static void __init
+setup_resources(void)
+{
+	struct resource *res;
+	int i;
+
+	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+		res = alloc_bootmem_low(sizeof(struct resource));
+		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+		switch (memory_chunk[i].type) {
+		case CHUNK_READ_WRITE:
+			res->name = "System RAM";
+			break;
+		case CHUNK_READ_ONLY:
+			res->name = "System ROM";
+			res->flags |= IORESOURCE_READONLY;
+			break;
+		default:
+			res->name = "reserved";
+		}
+		res->start = memory_chunk[i].addr;
+		res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
+		request_resource(&iomem_resource, res);
+		request_resource(res, &code_resource);
+		request_resource(res, &data_resource);
+	}
+}
+
+static void __init
+setup_memory(void)
+{
+        unsigned long bootmap_size;
+	unsigned long start_pfn, end_pfn, init_pfn;
+	unsigned long last_rw_end;
+	int i;
+
+	/*
+	 * partially used pages are not usable - thus
+	 * we are rounding upwards:
+	 */
+	start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	end_pfn = max_pfn = memory_end >> PAGE_SHIFT;
+
+	/* Initialize storage key for kernel pages */
+	for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
+		page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+
+	/*
+	 * Initialize the boot-time allocator (with low memory only):
+	 */
+	bootmap_size = init_bootmem(start_pfn, end_pfn);
+
+	/*
+	 * Register RAM areas with the bootmem allocator.
+	 */
+	last_rw_end = start_pfn;
+
+	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+		unsigned long start_chunk, end_chunk;
+
+		if (memory_chunk[i].type != CHUNK_READ_WRITE)
+			continue;
+		start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
+		start_chunk >>= PAGE_SHIFT;
+		end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
+		end_chunk >>= PAGE_SHIFT;
+		if (start_chunk < start_pfn)
+			start_chunk = start_pfn;
+		if (end_chunk > end_pfn)
+			end_chunk = end_pfn;
+		if (start_chunk < end_chunk) {
+			/* Initialize storage key for RAM pages */
+			for (init_pfn = start_chunk ; init_pfn < end_chunk;
+			     init_pfn++)
+				page_set_storage_key(init_pfn << PAGE_SHIFT,
+						     PAGE_DEFAULT_KEY);
+			free_bootmem(start_chunk << PAGE_SHIFT,
+				     (end_chunk - start_chunk) << PAGE_SHIFT);
+			if (last_rw_end < start_chunk)
+				add_memory_hole(last_rw_end, start_chunk - 1);
+			last_rw_end = end_chunk;
+		}
+	}
+
+	psw_set_key(PAGE_DEFAULT_KEY);
+
+	if (last_rw_end < end_pfn - 1)
+		add_memory_hole(last_rw_end, end_pfn - 1);
+
+	/*
+	 * Reserve the bootmem bitmap itself as well. We do this in two
+	 * steps (first step was init_bootmem()) because this catches
+	 * the (very unlikely) case of us accidentally initializing the
+	 * bootmem allocator with an invalid RAM area.
+	 */
+	reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (INITRD_START) {
+		if (INITRD_START + INITRD_SIZE <= memory_end) {
+			reserve_bootmem(INITRD_START, INITRD_SIZE);
+			initrd_start = INITRD_START;
+			initrd_end = initrd_start + INITRD_SIZE;
+		} else {
+			printk("initrd extends beyond end of memory "
+			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+			       initrd_start + INITRD_SIZE, memory_end);
+			initrd_start = initrd_end = 0;
+		}
+	}
+#endif
+}
+
+/*
+ * Setup function called from init/main.c just after the banner
+ * was printed.
+ */
+
+void __init
+setup_arch(char **cmdline_p)
+{
+        /*
+         * print what head.S has found out about the machine
+         */
+#ifndef CONFIG_ARCH_S390X
+	printk((MACHINE_IS_VM) ?
+	       "We are running under VM (31 bit mode)\n" :
+	       "We are running native (31 bit mode)\n");
+	printk((MACHINE_HAS_IEEE) ?
+	       "This machine has an IEEE fpu\n" :
+	       "This machine has no IEEE fpu\n");
+#else /* CONFIG_ARCH_S390X */
+	printk((MACHINE_IS_VM) ?
+	       "We are running under VM (64 bit mode)\n" :
+	       "We are running native (64 bit mode)\n");
+#endif /* CONFIG_ARCH_S390X */
+
+        ROOT_DEV = Root_RAM0;
+#ifndef CONFIG_ARCH_S390X
+	memory_end = memory_size & ~0x400000UL;  /* align memory end to 4MB */
+        /*
+         * We need some free virtual space to be able to do vmalloc.
+         * On a machine with 2GB memory we make sure that we have at
+         * least 128 MB free space for vmalloc.
+         */
+        if (memory_end > 1920*1024*1024)
+                memory_end = 1920*1024*1024;
+#else /* CONFIG_ARCH_S390X */
+	memory_end = memory_size & ~0x200000UL;  /* detected in head.s */
+#endif /* CONFIG_ARCH_S390X */
+
+	init_mm.start_code = PAGE_OFFSET;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+	init_mm.brk = (unsigned long) &_end;
+
+	parse_cmdline_early(cmdline_p);
+
+	setup_memory();
+	setup_resources();
+	setup_lowcore();
+
         cpu_init();
         __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
 
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 061e811..8ca4856 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -244,7 +244,7 @@
  */
 static inline void stop_hz_timer(void)
 {
-	__u64 timer;
+	__u64 timer, todval;
 
 	if (sysctl_hz_timer != 0)
 		return;
@@ -265,8 +265,14 @@
 	 * for the next event.
 	 */
 	timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
-	timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
-	asm volatile ("SCKC %0" : : "m" (timer));
+	todval = -1ULL;
+	/* Be careful about overflows. */
+	if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
+		timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
+		if (timer >= jiffies_timer_cc)
+			todval = timer;
+	}
+	asm volatile ("SCKC %0" : : "m" (todval));
 }
 
 /*
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index bb6cf02..fa07265 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -122,12 +122,17 @@
 	struct vtimer_queue *vt_list;
 
 	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
-	set_vtimer(vt_list->idle);
+
+	/* CPU timer interrupt is pending, don't reprogramm it */
+	if (vt_list->idle & 1LL<<63)
+		return;
+
+	if (!list_empty(&vt_list->list))
+		set_vtimer(vt_list->idle);
 }
 
 static void stop_cpu_timer(void)
 {
-	__u64 done;
 	struct vtimer_queue *vt_list;
 
 	vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
@@ -138,21 +143,17 @@
 		goto fire;
 	}
 
-	/* store progress */
-	asm volatile ("STPT %0" : "=m" (done));
+	/* store the actual expire value */
+	asm volatile ("STPT %0" : "=m" (vt_list->idle));
 
 	/*
-	 * If done is negative we do not stop the CPU timer
-	 * because we will get instantly an interrupt that
-	 * will start the CPU timer again.
+	 * If the CPU timer is negative we don't reprogramm
+	 * it because we will get instantly an interrupt.
 	 */
-	if (done & 1LL<<63)
+	if (vt_list->idle & 1LL<<63)
 		return;
-	else
-		vt_list->offset += vt_list->to_expire - done;
 
-	/* save the actual expire value */
-	vt_list->idle = done;
+	vt_list->offset += vt_list->to_expire - vt_list->idle;
 
 	/*
 	 * We cannot halt the CPU timer, we just write a value that
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index d30cdb4..f5a5bc0 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -20,6 +20,11 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 
+static char *sender = "VMRMSVM";
+module_param(sender, charp, 0);
+MODULE_PARM_DESC(sender,
+		 "Guest name that may send SMSG messages (default VMRMSVM)");
+
 #include "../../../drivers/s390/net/smsgiucv.h"
 
 #define CMM_NR_PAGES ((PAGE_SIZE / sizeof(unsigned long)) - 2)
@@ -367,10 +372,12 @@
 #ifdef CONFIG_CMM_IUCV
 #define SMSG_PREFIX "CMM"
 static void
-cmm_smsg_target(char *msg)
+cmm_smsg_target(char *from, char *msg)
 {
 	long pages, seconds;
 
+	if (strlen(sender) > 0 && strcmp(from, sender) != 0)
+		return;
 	if (!cmm_skip_blanks(msg + strlen(SMSG_PREFIX), &msg))
 		return;
 	if (strncmp(msg, "SHRINK", 6) == 0) {
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 8e723bc..6ec5cd9 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -101,6 +101,7 @@
 extern unsigned long __init_begin;
 extern unsigned long __init_end;
 
+extern unsigned long __initdata zholes_size[];
 /*
  * paging_init() sets up the page tables
  */
@@ -163,10 +164,13 @@
         local_flush_tlb();
 
 	{
-		unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+		unsigned long zones_size[MAX_NR_ZONES];
 
+		memset(zones_size, 0, sizeof(zones_size));
 		zones_size[ZONE_DMA] = max_low_pfn;
-		free_area_init(zones_size);
+		free_area_init_node(0, &contig_page_data, zones_size,
+				    __pa(PAGE_OFFSET) >> PAGE_SHIFT,
+				    zholes_size);
 	}
         return;
 }
@@ -184,9 +188,10 @@
           _KERN_REGION_TABLE;
 	static const int ssm_mask = 0x04000000L;
 
-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long dma_pfn, high_pfn;
 
+	memset(zones_size, 0, sizeof(zones_size));
 	dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
 	high_pfn = max_low_pfn;
 
@@ -198,8 +203,8 @@
 	}
 
 	/* Initialize mem_map[].  */
-	free_area_init(zones_size);
-
+	free_area_init_node(0, &contig_page_data, zones_size,
+			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 
 	/*
 	 * map whole physical memory to virtual memory (identity mapping) 
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 722ea1d..3468d51 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -693,6 +693,10 @@
 
 endmenu
 
+config ISA_DMA_API
+	bool
+	depends on MPC1211
+	default y
 
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 1b0dfb4..b28919b 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -20,6 +20,7 @@
 #include <linux/user.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -197,7 +198,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -228,7 +229,7 @@
 		struct pt_regs *dummy = NULL;
 
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		if ((child->ptrace & PT_DTRACE) == 0) {
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 800288c..fd20009 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -255,7 +256,7 @@
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -285,7 +286,7 @@
 		struct pt_regs *regs;
 
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		if ((child->ptrace & PT_DTRACE) == 0) {
diff --git a/arch/sh64/kernel/sys_sh64.c b/arch/sh64/kernel/sys_sh64.c
index 4546845..58ff7d5 100644
--- a/arch/sh64/kernel/sys_sh64.c
+++ b/arch/sh64/kernel/sys_sh64.c
@@ -283,18 +283,3 @@
 	up_read(&uts_sem);
 	return err?-EFAULT:0;
 }
-
-/* Copy from mips version */
-asmlinkage long sys_shmatcall(int shmid, char __user *shmaddr,
-		int shmflg)
-{
-	unsigned long raddr;
-	int err;
-
-	err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-	if (err)
-		return err;
-
-	err = raddr;
-	return err;
-}
diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S
index 8ed417d..6aabc63 100644
--- a/arch/sh64/kernel/syscalls.S
+++ b/arch/sh64/kernel/syscalls.S
@@ -268,7 +268,7 @@
 	.long sys_msgrcv
 	.long sys_msgget
 	.long sys_msgctl
-	.long sys_shmatcall
+	.long sys_shmat
 	.long sys_shmdt			/* 245 */
 	.long sys_shmget
 	.long sys_shmctl
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 143fe2f..2c216ff 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -83,9 +83,6 @@
  */
 void cpu_idle(void)
 {
-	if (current->pid != 0)
-		goto out;
-
 	/* endless idle loop with no priority at all */
 	for (;;) {
 		if (ARCH_SUN4C_SUN4) {
@@ -126,8 +123,6 @@
 		schedule();
 		check_pgt_cache();
 	}
-out:
-	return;
 }
 
 #else
@@ -333,6 +328,17 @@
 	printk("\n");
 }
 
+void dump_stack(void)
+{
+	unsigned long *ksp;
+
+	__asm__ __volatile__("mov	%%fp, %0"
+			     : "=r" (ksp));
+	show_stack(current, ksp);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
 /*
  * Note: sparc64 has a pretty intricated thread_saved_pc, check it out.
  */
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index c4f93bd..475c4c1 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -526,7 +527,7 @@
 		addr = 1;
 
 	case PTRACE_CONT: { /* restart after signal. */
-		if (data > _NSIG) {
+		if (!valid_signal(data)) {
 			pt_error_return(regs, EIO);
 			goto out_tsk;
 		}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index f91b0e8..1bd430d 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -20,6 +20,7 @@
 #include <linux/in6.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
+#include <linux/syscalls.h>
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #endif
@@ -89,6 +90,9 @@
 extern void ___set_bit(void);
 extern void ___clear_bit(void);
 extern void ___change_bit(void);
+extern void ___rw_read_enter(void);
+extern void ___rw_read_exit(void);
+extern void ___rw_write_enter(void);
 
 /* Alias functions whose names begin with "." and export the aliases.
  * The module references will be fixed up by module_frob_arch_sections.
@@ -121,9 +125,9 @@
 #endif
 #else
 // XXX find what uses (or used) these.
-// EXPORT_SYMBOL_PRIVATE(_rw_read_enter);
-// EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
-// EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
+EXPORT_SYMBOL(___rw_read_enter);
+EXPORT_SYMBOL(___rw_read_exit);
+EXPORT_SYMBOL(___rw_write_enter);
 #endif
 /* semaphores */
 EXPORT_SYMBOL(__up);
@@ -144,6 +148,9 @@
 EXPORT_SYMBOL(___clear_bit);
 EXPORT_SYMBOL(___change_bit);
 
+/* Per-CPU information table */
+EXPORT_PER_CPU_SYMBOL(__cpu_data);
+
 #ifdef CONFIG_SMP
 /* IRQ implementation. */
 EXPORT_SYMBOL(synchronize_irq);
@@ -151,6 +158,10 @@
 /* Misc SMP information */
 EXPORT_SYMBOL(__cpu_number_map);
 EXPORT_SYMBOL(__cpu_logical_map);
+
+/* CPU online map and active count. */
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(phys_cpu_present_map);
 #endif
 
 EXPORT_SYMBOL(__udelay);
@@ -332,3 +343,6 @@
 
 /* Sun Power Management Idle Handler */
 EXPORT_SYMBOL(pm_idle);
+
+/* Binfmt_misc needs this */
+EXPORT_SYMBOL(sys_close);
diff --git a/arch/sparc/prom/memory.c b/arch/sparc/prom/memory.c
index 46aa51a..c20e530 100644
--- a/arch/sparc/prom/memory.c
+++ b/arch/sparc/prom/memory.c
@@ -47,9 +47,9 @@
 	char *tmpaddr;
 	char *lowest;
 
-	for(i=0; thislist[i].theres_more != 0; i++) {
+	for(i=0; thislist[i].theres_more; i++) {
 		lowest = thislist[i].start_adr;
-		for(mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
+		for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
 			if(thislist[mitr].start_adr < lowest) {
 				lowest = thislist[mitr].start_adr;
 				swapi = mitr;
@@ -85,7 +85,7 @@
 			prom_phys_total[iter].num_bytes = mptr->num_bytes;
 			prom_phys_total[iter].theres_more = &prom_phys_total[iter+1];
 		}
-		prom_phys_total[iter-1].theres_more = 0x0;
+		prom_phys_total[iter-1].theres_more = NULL;
 		/* Second, the total prom taken descriptors. */
 		for(mptr = (*(romvec->pv_v0mem.v0_prommap)), iter=0;
 		    mptr; mptr=mptr->theres_more, iter++) {
@@ -93,7 +93,7 @@
 			prom_prom_taken[iter].num_bytes = mptr->num_bytes;
 			prom_prom_taken[iter].theres_more = &prom_prom_taken[iter+1];
 		}
-		prom_prom_taken[iter-1].theres_more = 0x0;
+		prom_prom_taken[iter-1].theres_more = NULL;
 		/* Last, the available physical descriptors. */
 		for(mptr = (*(romvec->pv_v0mem.v0_available)), iter=0;
 		    mptr; mptr=mptr->theres_more, iter++) {
@@ -101,7 +101,7 @@
 			prom_phys_avail[iter].num_bytes = mptr->num_bytes;
 			prom_phys_avail[iter].theres_more = &prom_phys_avail[iter+1];
 		}
-		prom_phys_avail[iter-1].theres_more = 0x0;
+		prom_phys_avail[iter-1].theres_more = NULL;
 		/* Sort all the lists. */
 		prom_sortmemlist(prom_phys_total);
 		prom_sortmemlist(prom_prom_taken);
@@ -124,7 +124,7 @@
 			prom_phys_avail[iter].theres_more =
 				&prom_phys_avail[iter+1];
 		}
-		prom_phys_avail[iter-1].theres_more = 0x0;
+		prom_phys_avail[iter-1].theres_more = NULL;
 
 		num_regs = prom_getproperty(node, "reg",
 					    (char *) prom_reg_memlist,
@@ -138,7 +138,7 @@
 			prom_phys_total[iter].theres_more =
 				&prom_phys_total[iter+1];
 		}
-		prom_phys_total[iter-1].theres_more = 0x0;
+		prom_phys_total[iter-1].theres_more = NULL;
 
 		node = prom_getchild(prom_root_node);
 		node = prom_searchsiblings(node, "virtual-memory");
@@ -158,7 +158,7 @@
 			prom_prom_taken[iter].theres_more =
 				&prom_prom_taken[iter+1];
 		}
-		prom_prom_taken[iter-1].theres_more = 0x0;
+		prom_prom_taken[iter-1].theres_more = NULL;
 
 		prom_sortmemlist(prom_prom_taken);
 
@@ -182,15 +182,15 @@
 	case PROM_SUN4:
 #ifdef CONFIG_SUN4	
 		/* how simple :) */
-		prom_phys_total[0].start_adr = 0x0;
+		prom_phys_total[0].start_adr = NULL;
 		prom_phys_total[0].num_bytes = *(sun4_romvec->memorysize);
-		prom_phys_total[0].theres_more = 0x0;
-		prom_prom_taken[0].start_adr = 0x0; 
+		prom_phys_total[0].theres_more = NULL;
+		prom_prom_taken[0].start_adr = NULL; 
 		prom_prom_taken[0].num_bytes = 0x0;
-		prom_prom_taken[0].theres_more = 0x0;
-		prom_phys_avail[0].start_adr = 0x0;
+		prom_prom_taken[0].theres_more = NULL;
+		prom_phys_avail[0].start_adr = NULL;
 		prom_phys_avail[0].num_bytes = *(sun4_romvec->memoryavail);
-		prom_phys_avail[0].theres_more = 0x0;
+		prom_phys_avail[0].theres_more = NULL;
 #endif
 		break;
 
diff --git a/arch/sparc/prom/sun4prom.c b/arch/sparc/prom/sun4prom.c
index 69ca735..00390a2 100644
--- a/arch/sparc/prom/sun4prom.c
+++ b/arch/sparc/prom/sun4prom.c
@@ -151,7 +151,7 @@
 	 * have more time, we can teach the penguin to say "By your
 	 * command" or "Activating turbo boost, Michael". :-)
 	 */
-	sun4_romvec->setLEDs(0x0);
+	sun4_romvec->setLEDs(NULL);
 	
 	printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n",
 		sun4_romvec->monid,
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index fb11896..a72fd15 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -118,6 +118,7 @@
 
 config HW_CONSOLE
 	bool
+	depends on VT
 	default y
 
 config SMP
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index a38cb50..4dcb8af 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -756,7 +756,7 @@
 		clear_softint(clr_mask);
 	}
 #else
-	int should_forward = 1;
+	int should_forward = 0;
 
 	clear_softint(1 << irq);
 #endif
@@ -1007,10 +1007,10 @@
 	}
 	upa_writel(tid | IMAP_VALID, imap);
 
-	while (!cpu_online(goal_cpu)) {
+	do {
 		if (++goal_cpu >= NR_CPUS)
 			goal_cpu = 0;
-	}
+	} while (!cpu_online(goal_cpu));
 
 	return goal_cpu;
 }
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 26d3ec4..a0cd2b2 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -62,9 +62,6 @@
  */
 void cpu_idle(void)
 {
-	if (current->pid != 0)
-		return;
-
 	/* endless idle loop with no priority at all */
 	for (;;) {
 		/* If current->work.need_resched is zero we should really
@@ -80,7 +77,6 @@
 		schedule();
 		check_pgt_cache();
 	}
-	return;
 }
 
 #else
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 5f080cf..80a76e2 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -19,6 +19,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/asi.h>
 #include <asm/pgtable.h>
@@ -559,7 +560,7 @@
 		addr = 1;
 
 	case PTRACE_CONT: { /* restart after signal. */
-		if (data > _NSIG) {
+		if (!valid_signal(data)) {
 			pt_error_return(regs, EIO);
 			goto out_tsk;
 		}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index cad5a11..e78cc53 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -278,7 +278,7 @@
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(__pte_alloc_one_kernel);
+EXPORT_SYMBOL(pte_alloc_one_kernel);
 #ifndef CONFIG_SMP
 EXPORT_SYMBOL(pgt_quicklists);
 #endif
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 6a717d4..71b4e38 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -48,7 +48,7 @@
 
 DEFINE_SPINLOCK(mostek_lock);
 DEFINE_SPINLOCK(rtc_lock);
-unsigned long mstk48t02_regs = 0UL;
+void __iomem *mstk48t02_regs = NULL;
 #ifdef CONFIG_PCI
 unsigned long ds1287_regs = 0UL;
 #endif
@@ -59,8 +59,8 @@
 
 EXPORT_SYMBOL(jiffies_64);
 
-static unsigned long mstk48t08_regs = 0UL;
-static unsigned long mstk48t59_regs = 0UL;
+static void __iomem *mstk48t08_regs;
+static void __iomem *mstk48t59_regs;
 
 static int set_rtc_mmss(unsigned long);
 
@@ -520,7 +520,7 @@
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
 static void __init kick_start_clock(void)
 {
-	unsigned long regs = mstk48t02_regs;
+	void __iomem *regs = mstk48t02_regs;
 	u8 sec, tmp;
 	int i, count;
 
@@ -604,7 +604,7 @@
 /* Return nonzero if the clock chip battery is low. */
 static int __init has_low_battery(void)
 {
-	unsigned long regs = mstk48t02_regs;
+	void __iomem *regs = mstk48t02_regs;
 	u8 data1, data2;
 
 	spin_lock_irq(&mostek_lock);
@@ -623,7 +623,7 @@
 static void __init set_system_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
-	unsigned long mregs = mstk48t02_regs;
+	void __iomem *mregs = mstk48t02_regs;
 #ifdef CONFIG_PCI
 	unsigned long dregs = ds1287_regs;
 #else
@@ -843,7 +843,8 @@
 			    !strcmp(model, "m5823")) {
 				ds1287_regs = edev->resource[0].start;
 			} else {
-				mstk48t59_regs = edev->resource[0].start;
+				mstk48t59_regs = (void __iomem *)
+					edev->resource[0].start;
 				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
 			}
 			break;
@@ -865,7 +866,8 @@
 			    !strcmp(model, "m5823")) {
 				ds1287_regs = isadev->resource.start;
 			} else {
-				mstk48t59_regs = isadev->resource.start;
+				mstk48t59_regs = (void __iomem *)
+					isadev->resource.start;
 				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
 			}
 			break;
@@ -893,21 +895,24 @@
 		}
 
 		if(model[5] == '0' && model[6] == '2') {
-			mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |
-					  (((u64)clk_reg[0].which_io)<<32UL));
+			mstk48t02_regs = (void __iomem *)
+				(((u64)clk_reg[0].phys_addr) |
+				 (((u64)clk_reg[0].which_io)<<32UL));
 		} else if(model[5] == '0' && model[6] == '8') {
-			mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |
-					  (((u64)clk_reg[0].which_io)<<32UL));
+			mstk48t08_regs = (void __iomem *)
+				(((u64)clk_reg[0].phys_addr) |
+				 (((u64)clk_reg[0].which_io)<<32UL));
 			mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
 		} else {
-			mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |
-					  (((u64)clk_reg[0].which_io)<<32UL));
+			mstk48t59_regs = (void __iomem *)
+				(((u64)clk_reg[0].phys_addr) |
+				 (((u64)clk_reg[0].which_io)<<32UL));
 			mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
 		}
 		break;
 	}
 
-	if (mstk48t02_regs != 0UL) {
+	if (mstk48t02_regs != NULL) {
 		/* Report a low battery voltage condition. */
 		if (has_low_battery())
 			prom_printf("NVRAM: Low battery voltage!\n");
@@ -1087,7 +1092,7 @@
 static int set_rtc_mmss(unsigned long nowtime)
 {
 	int real_seconds, real_minutes, chip_minutes;
-	unsigned long mregs = mstk48t02_regs;
+	void __iomem *mregs = mstk48t02_regs;
 #ifdef CONFIG_PCI
 	unsigned long dregs = ds1287_regs;
 #else
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index db6fa77..9c52220 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1114,7 +1114,7 @@
 #else
 #define DC_ALIAS_SHIFT	0
 #endif
-pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
 	struct page *page;
 	unsigned long color;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 9a23df1..c529218 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -244,6 +244,7 @@
 
 config HIGHMEM
 	bool "Highmem support"
+	depends on !64BIT
 
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
diff --git a/arch/um/Kconfig_i386 b/arch/um/Kconfig_i386
index 203c242..e41f374 100644
--- a/arch/um/Kconfig_i386
+++ b/arch/um/Kconfig_i386
@@ -1,4 +1,8 @@
-config 64_BIT
+config UML_X86
+	bool
+	default y
+
+config 64BIT
 	bool
 	default n
 
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
index 768dc66..fd8d7e8 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig_x86_64
@@ -1,4 +1,8 @@
-config 64_BIT
+config UML_X86
+	bool
+	default y
+
+config 64BIT
 	bool
 	default y
 
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 97bca6b..f2a0c40 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -17,7 +17,7 @@
 
 # Have to precede the include because the included Makefiles reference them.
 SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \
-	arch-signal.h module.h vm-flags.h
+	module.h vm-flags.h elf.h
 SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 
 # XXX: The "os" symlink is only used by arch/um/include/os.h, which includes
@@ -44,6 +44,11 @@
 endif
 
 ARCH_INCLUDE	:= -I$(ARCH_DIR)/include
+ifneq ($(KBUILD_SRC),)
+ARCH_INCLUDE	+= -I$(ARCH_DIR)/include2
+ARCH_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/include
+MRPROPER_DIRS	+= $(ARCH_DIR)/include2
+endif
 SYS_DIR		:= $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
 include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -94,17 +99,18 @@
   echo '		   find in the kernel root.'
 endef
 
+ifneq ($(KBUILD_SRC),)
+$(shell mkdir -p $(ARCH_DIR) && ln -fsn $(srctree)/$(ARCH_DIR)/Kconfig_$(SUBARCH) $(ARCH_DIR)/Kconfig_arch)
+CLEAN_FILES += $(ARCH_DIR)/Kconfig_arch
+else
 $(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch)
+endif
 
-prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
-	$(ARCH_DIR)/kernel/vmlinux.lds.S
+prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
 
-LD_SCRIPT-$(CONFIG_LD_SCRIPT_STATIC) := uml.lds.S
-LD_SCRIPT-$(CONFIG_LD_SCRIPT_DYN) := dyn.lds.S
-
 CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
@@ -126,7 +132,7 @@
 	$(CC) $(CFLAGS_vmlinux) -o $@ \
 	-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
 	-Wl,--start-group $(vmlinux-main) -Wl,--end-group \
-	-L/usr/lib -lutil \
+	-lutil \
 	$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) \
 	FORCE ,$^) ; rm -f linux
 endef
@@ -145,31 +151,42 @@
 	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
 		-o -name '*.gcov' \) -type f -print | xargs rm -f
 
-#We need to re-preprocess this when the symlink dest changes.
-#So we touch it when needed.
-$(ARCH_DIR)/kernel/vmlinux.lds.S: FORCE
-	$(Q)if [ "$(shell readlink $@)" != "$(LD_SCRIPT-y)" ]; then \
-		echo '  SYMLINK $@'; \
-		ln -sf $(LD_SCRIPT-y) $@; \
-		touch $@; \
-	fi;
-
 $(SYMLINK_HEADERS):
 	@echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+	ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
+else
 	$(Q)cd $(TOPDIR)/$(dir $@) ; \
 	ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
+endif
 
 include/asm-um/arch:
 	@echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p include/asm-um
+	$(Q)ln -fsn $(srctree)/include/asm-$(SUBARCH) include/asm-um/arch
+else
 	$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
+endif
 
 $(ARCH_DIR)/include/sysdep:
 	@echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p $(ARCH_DIR)/include
+	$(Q)mkdir -p $(ARCH_DIR)/include2
+	$(Q)ln -fsn sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
+	$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include2/sysdep
+else
 	$(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
+endif
 
 $(ARCH_DIR)/os:
 	@echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+	$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/os-$(OS) $(ARCH_DIR)/os
+else
 	$(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
+endif
 
 # Generated files
 define filechk_umlconfig
@@ -179,10 +196,31 @@
 $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
 	$(call filechk,umlconfig)
 
+$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
+	$(CC) $(USER_CFLAGS) -S -o $@ $<
+
+$(ARCH_DIR)/user-offsets.h: $(ARCH_DIR)/user-offsets.s
+	$(call filechk,gen-asm-offsets)
+
+CLEAN_FILES += $(ARCH_DIR)/user-offsets.s  $(ARCH_DIR)/user-offsets.h
+
+$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \
+				   $(ARCH_SYMLINKS) \
+				   $(SYS_DIR)/sc.h \
+				   include/asm include/linux/version.h \
+				   include/config/MARKER \
+				   $(ARCH_DIR)/include/user_constants.h
+	$(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $<
+
+$(ARCH_DIR)/kernel-offsets.h: $(ARCH_DIR)/kernel-offsets.s
+	$(call filechk,gen-asm-offsets)
+
+CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s  $(ARCH_DIR)/kernel-offsets.h
+
 $(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task
 	$(call filechk,gen_header)
 
-$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os/util/mk_user_constants
+$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os-$(OS)/util/mk_user_constants
 	$(call filechk,gen_header)
 
 $(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
@@ -191,20 +229,20 @@
 $(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
 	$(call filechk,gen_header)
 
-$(ARCH_DIR)/os/util/mk_user_constants: $(ARCH_DIR)/os/util FORCE ;
+$(ARCH_DIR)/os-$(OS)/util/mk_user_constants: $(ARCH_DIR)/os-$(OS)/util FORCE ;
 
 $(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \
 	FORCE ;
 
 $(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
 
-$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE
+$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h $(ARCH_DIR)/kernel-offsets.h FORCE
 	$(Q)$(MAKE) $(build)=$@
 
-$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
+$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
 	$(Q)$(MAKE) $(build)=$@
 
-$(ARCH_DIR)/os/util: scripts_basic FORCE
+$(ARCH_DIR)/os-$(OS)/util: scripts_basic FORCE
 	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 97b223b..29e182d 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -1,4 +1,4 @@
-SUBARCH_CORE := arch/um/sys-i386/
+SUBARCH_CORE := arch/um/sys-i386/ arch/i386/crypto/
 
 TOP_ADDR := $(CONFIG_TOP_ADDR)
 
@@ -32,10 +32,10 @@
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
 	$(call filechk,gen_header)
 
-$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
 	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_DIR)/kernel-offsets.h FORCE
 	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
 $(SYS_UTIL_DIR): scripts_basic include/asm FORCE
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index a779711..3214456 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -23,10 +23,10 @@
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
 	$(call filechk,gen_header)
 
-$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
 	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(GEN_HEADERS) $(ARCH_DIR)/kernel-offsets.h FORCE
 	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
 CLEAN_FILES += $(SYS_HEADERS)
diff --git a/arch/um/defconfig b/arch/um/defconfig
index fc3075c..4067c3a 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk1
-# Sun Mar 20 16:53:00 2005
+# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2
+# Sun Apr 24 19:46:10 2005
 #
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_UML=y
@@ -15,7 +15,8 @@
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
-# CONFIG_64_BIT is not set
+CONFIG_UML_X86=y
+# CONFIG_64BIT is not set
 CONFIG_TOP_ADDR=0xc0000000
 # CONFIG_3_LEVEL_PGTABLES is not set
 CONFIG_ARCH_HAS_SC_SIGNALS=y
@@ -41,6 +42,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -158,7 +160,6 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -412,6 +413,5 @@
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_PT_PROXY=y
-# CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
 # CONFIG_SYSCALL_DEBUG is not set
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 1f77deb..0150038 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -22,7 +22,7 @@
 #ifdef CONFIG_NOCONFIG_CHAN
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 	return(NULL);
 }
@@ -30,27 +30,27 @@
 static int not_configged_open(int input, int output, int primary, void *data,
 			      char **dev_out)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 	return(-ENODEV);
 }
 
 static void not_configged_close(int fd, void *data)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 }
 
 static int not_configged_read(int fd, char *c_out, void *data)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 	return(-EIO);
 }
 
 static int not_configged_write(int fd, const char *buf, int len, void *data)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 	return(-EIO);
 }
@@ -58,7 +58,7 @@
 static int not_configged_console_write(int fd, const char *buf, int len,
 				       void *data)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 	return(-EIO);
 }
@@ -66,14 +66,14 @@
 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
 				     unsigned short *cols)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 	return(-ENODEV);
 }
 
 static void not_configged_free(void *data)
 {
-	printk(KERN_ERR "Using a channel type which is configured out of "
+	printf(KERN_ERR "Using a channel type which is configured out of "
 	       "UML\n");
 }
 
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 6924f27..025d3be 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -39,19 +39,69 @@
 	line_interrupt(line->driver->read_irq, arg, NULL);
 }
 
-static int write_room(struct line *dev)
+/* Returns the free space inside the ring buffer of this line.
+ *
+ * Should be called while holding line->lock (this does not modify datas).
+ */
+static int write_room(struct line *line)
 {
 	int n;
 
-	if (dev->buffer == NULL)
-		return (LINE_BUFSIZE - 1);
+	if (line->buffer == NULL)
+		return LINE_BUFSIZE - 1;
 
-	n = dev->head - dev->tail;
+	/* This is for the case where the buffer is wrapped! */
+	n = line->head - line->tail;
+
 	if (n <= 0)
-		n = LINE_BUFSIZE + n;
-	return (n - 1);
+		n = LINE_BUFSIZE + n; /* The other case */
+	return n - 1;
 }
 
+int line_write_room(struct tty_struct *tty)
+{
+	struct line *line = tty->driver_data;
+	unsigned long flags;
+	int room;
+
+	if (tty->stopped)
+		return 0;
+
+	spin_lock_irqsave(&line->lock, flags);
+	room = write_room(line);
+	spin_unlock_irqrestore(&line->lock, flags);
+
+	/*XXX: Warning to remove */
+	if (0 == room)
+		printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
+		       __FUNCTION__,tty->name);
+	return room;
+}
+
+int line_chars_in_buffer(struct tty_struct *tty)
+{
+	struct line *line = tty->driver_data;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&line->lock, flags);
+
+	/*write_room subtracts 1 for the needed NULL, so we readd it.*/
+	ret = LINE_BUFSIZE - (write_room(line) + 1);
+	spin_unlock_irqrestore(&line->lock, flags);
+
+	return ret;
+}
+
+/*
+ * This copies the content of buf into the circular buffer associated with
+ * this line.
+ * The return value is the number of characters actually copied, i.e. the ones
+ * for which there was space: this function is not supposed to ever flush out
+ * the circular buffer.
+ *
+ * Must be called while holding line->lock!
+ */
 static int buffer_data(struct line *line, const char *buf, int len)
 {
 	int end, room;
@@ -70,48 +120,95 @@
 	len = (len > room) ? room : len;
 
 	end = line->buffer + LINE_BUFSIZE - line->tail;
-	if(len < end){
+
+	if (len < end){
 		memcpy(line->tail, buf, len);
 		line->tail += len;
-	}
-	else {
+	} else {
+		/* The circular buffer is wrapping */
 		memcpy(line->tail, buf, end);
 		buf += end;
 		memcpy(line->buffer, buf, len - end);
 		line->tail = line->buffer + len - end;
 	}
 
-	return(len);
+	return len;
 }
 
+/*
+ * Flushes the ring buffer to the output channels. That is, write_chan is
+ * called, passing it line->head as buffer, and an appropriate count.
+ *
+ * On exit, returns 1 when the buffer is empty,
+ * 0 when the buffer is not empty on exit,
+ * and -errno when an error occurred.
+ *
+ * Must be called while holding line->lock!*/
 static int flush_buffer(struct line *line)
 {
 	int n, count;
 
 	if ((line->buffer == NULL) || (line->head == line->tail))
-		return(1);
+		return 1;
 
 	if (line->tail < line->head) {
+		/* line->buffer + LINE_BUFSIZE is the end of the buffer! */
 		count = line->buffer + LINE_BUFSIZE - line->head;
+
 		n = write_chan(&line->chan_list, line->head, count,
 			       line->driver->write_irq);
 		if (n < 0)
-			return(n);
-		if (n == count)
+			return n;
+		if (n == count) {
+			/* We have flushed from ->head to buffer end, now we
+			 * must flush only from the beginning to ->tail.*/
 			line->head = line->buffer;
-		else {
+		} else {
 			line->head += n;
-			return(0);
+			return 0;
 		}
 	}
 
 	count = line->tail - line->head;
 	n = write_chan(&line->chan_list, line->head, count, 
 		       line->driver->write_irq);
-	if(n < 0) return(n);
+
+	if(n < 0)
+		return n;
 
 	line->head += n;
-	return(line->head == line->tail);
+	return line->head == line->tail;
+}
+
+void line_flush_buffer(struct tty_struct *tty)
+{
+	struct line *line = tty->driver_data;
+	unsigned long flags;
+	int err;
+
+	/*XXX: copied from line_write, verify if it is correct!*/
+	if(tty->stopped)
+		return;
+		//return 0;
+
+	spin_lock_irqsave(&line->lock, flags);
+	err = flush_buffer(line);
+	/*if (err == 1)
+		err = 0;*/
+	spin_unlock_irqrestore(&line->lock, flags);
+	//return err;
+}
+
+/* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer
+ * and ->write. Hope it's not that bad.*/
+void line_flush_chars(struct tty_struct *tty)
+{
+	line_flush_buffer(tty);
+}
+
+void line_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	line_write(tty, &ch, sizeof(ch));
 }
 
 int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
@@ -120,38 +217,31 @@
 	unsigned long flags;
 	int n, err, ret = 0;
 
-	if(tty->stopped) return 0;
+	if(tty->stopped)
+		return 0;
 
-	down(&line->sem);
-	if(line->head != line->tail){
-		local_irq_save(flags);
+	spin_lock_irqsave(&line->lock, flags);
+	if (line->head != line->tail) {
 		ret = buffer_data(line, buf, len);
 		err = flush_buffer(line);
-		local_irq_restore(flags);
-		if(err <= 0 && (err != -EAGAIN || !ret))
+		if (err <= 0 && (err != -EAGAIN || !ret))
 			ret = err;
-	}
-	else {
+	} else {
 		n = write_chan(&line->chan_list, buf, len, 
 			       line->driver->write_irq);
-		if(n < 0){
+		if (n < 0) {
 			ret = n;
 			goto out_up;
 		}
 
 		len -= n;
 		ret += n;
-		if(len > 0)
+		if (len > 0)
 			ret += buffer_data(line, buf + n, len);
 	}
- out_up:
-	up(&line->sem);
-	return(ret);
-}
-
-void line_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	line_write(tty, &ch, sizeof(ch));
+out_up:
+	spin_unlock_irqrestore(&line->lock, flags);
+	return ret;
 }
 
 void line_set_termios(struct tty_struct *tty, struct termios * old)
@@ -159,11 +249,6 @@
 	/* nothing */
 }
 
-int line_chars_in_buffer(struct tty_struct *tty)
-{
-	return 0;
-}
-
 static struct {
 	int  cmd;
 	char *level;
@@ -250,7 +335,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	return(ret);
+	return ret;
 }
 
 static irqreturn_t line_write_interrupt(int irq, void *data,
@@ -260,18 +345,23 @@
 	struct line *line = tty->driver_data;
 	int err;
 
+	/* Interrupts are enabled here because we registered the interrupt with
+	 * SA_INTERRUPT (see line_setup_irq).*/
+
+	spin_lock_irq(&line->lock);
 	err = flush_buffer(line);
-	if(err == 0)
-		return(IRQ_NONE);
-	else if(err < 0){
+	if (err == 0) {
+		return IRQ_NONE;
+	} else if(err < 0) {
 		line->head = line->buffer;
 		line->tail = line->buffer;
 	}
+	spin_unlock_irq(&line->lock);
 
 	if(tty == NULL)
-		return(IRQ_NONE);
+		return IRQ_NONE;
 
-	if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
+	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
 	   (tty->ldisc.write_wakeup != NULL))
 		(tty->ldisc.write_wakeup)(tty);
 	
@@ -281,9 +371,9 @@
 	 * writes.
 	 */
 
-	if(waitqueue_active(&tty->write_wait))
+	if (waitqueue_active(&tty->write_wait))
 		wake_up_interruptible(&tty->write_wait);
-	return(IRQ_HANDLED);
+	return IRQ_HANDLED;
 }
 
 int line_setup_irq(int fd, int input, int output, struct tty_struct *tty)
@@ -292,15 +382,18 @@
 	struct line_driver *driver = line->driver;
 	int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
 
-	if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, 
+	if (input)
+		err = um_request_irq(driver->read_irq, fd, IRQ_READ,
 				       line_interrupt, flags, 
 				       driver->read_irq_name, tty);
-	if(err) return(err);
-	if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 
+	if (err)
+		return err;
+	if (output)
+		err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
 					line_write_interrupt, flags, 
 					driver->write_irq_name, tty);
 	line->have_irq = 1;
-	return(err);
+	return err;
 }
 
 void line_disable(struct tty_struct *tty, int current_irq)
@@ -336,7 +429,9 @@
 	line = &lines[tty->index];
 	tty->driver_data = line;
 
-	down(&line->sem);
+	/* The IRQ which takes this lock is not yet enabled and won't be run
+	 * before the end, so we don't need to use spin_lock_irq.*/
+	spin_lock(&line->lock);
 	if (tty->count == 1) {
 		if (!line->valid) {
 			err = -ENODEV;
@@ -349,6 +444,7 @@
 			err = open_chan(&line->chan_list);
 			if(err) goto out;
 		}
+		/* Here the interrupt is registered.*/
 		enable_chan(&line->chan_list, tty);
 		INIT_WORK(&line->task, line_timer_cb, tty);
 	}
@@ -362,21 +458,36 @@
 	line->count++;
 
 out:
-	up(&line->sem);
-	return(err);
+	spin_unlock(&line->lock);
+	return err;
 }
 
+static void unregister_winch(struct tty_struct *tty);
+
 void line_close(struct tty_struct *tty, struct file * filp)
 {
 	struct line *line = tty->driver_data;
 
-	down(&line->sem);
+	/* XXX: I assume this should be called in process context, not with
+         *  interrupts disabled!
+         */
+	spin_lock_irq(&line->lock);
+
+	/* We ignore the error anyway! */
+	flush_buffer(line);
+
 	line->count--;
 	if (tty->count == 1) {
 		line_disable(tty, -1);
 		tty->driver_data = NULL;
 	}
-	up(&line->sem);
+
+        if((line->count == 0) && line->sigio){
+                unregister_winch(tty);
+                line->sigio = 0;
+        }
+
+	spin_unlock_irq(&line->lock);
 }
 
 void close_lines(struct line *lines, int nlines)
@@ -387,31 +498,41 @@
 		close_chan(&lines[i].chan_list);
 }
 
-int line_setup(struct line *lines, int num, char *init, int all_allowed)
+/* Common setup code for both startup command line and mconsole initialization.
+ * @lines contains the the array (of size @num) to modify;
+ * @init is the setup string;
+ * @all_allowed is a boolean saying if we can setup the whole @lines
+ * at once. For instance, it will be usually true for startup init. (where we
+ * can use con=xterm) and false for mconsole.*/
+
+int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed)
 {
 	int i, n;
 	char *end;
 
-	if(*init == '=') n = -1;
-	else {
+	if(*init == '=') {
+		/* We said con=/ssl= instead of con#=, so we are configuring all
+		 * consoles at once.*/
+		n = -1;
+	} else {
 		n = simple_strtoul(init, &end, 0);
 		if(*end != '='){
 			printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 
 			       init);
-			return(0);
+			return 0;
 		}
 		init = end;
 	}
 	init++;
-	if((n >= 0) && (n >= num)){
+
+	if (n >= (signed int) num) {
 		printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
 		       n, num - 1);
-		return(0);
-	}
-	else if (n >= 0){
+		return 0;
+	} else if (n >= 0){
 		if (lines[n].count > 0) {
 			printk("line_setup - device %d is open\n", n);
-			return(0);
+			return 0;
 		}
 		if (lines[n].init_pri <= INIT_ONE){
 			lines[n].init_pri = INIT_ONE;
@@ -422,13 +543,11 @@
 				lines[n].valid = 1;
 			}	
 		}
-	}
-	else if(!all_allowed){
+	} else if(!all_allowed){
 		printk("line_setup - can't configure all devices from "
 		       "mconsole\n");
-		return(0);
-	}
-	else {
+		return 0;
+	} else {
 		for(i = 0; i < num; i++){
 			if(lines[i].init_pri <= INIT_ALL){
 				lines[i].init_pri = INIT_ALL;
@@ -440,21 +559,21 @@
 			}
 		}
 	}
-	return(1);
+	return 1;
 }
 
-int line_config(struct line *lines, int num, char *str)
+int line_config(struct line *lines, unsigned int num, char *str)
 {
 	char *new = uml_strdup(str);
 
 	if(new == NULL){
 		printk("line_config - uml_strdup failed\n");
-		return(-ENOMEM);
+		return -ENOMEM;
 	}
-	return(!line_setup(lines, num, new, 0));
+	return !line_setup(lines, num, new, 0);
 }
 
-int line_get_config(char *name, struct line *lines, int num, char *str, 
+int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
 		    int size, char **error_out)
 {
 	struct line *line;
@@ -464,47 +583,33 @@
 	dev = simple_strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
 		*error_out = "line_get_config failed to parse device number";
-		return(0);
+		return 0;
 	}
 
 	if((dev < 0) || (dev >= num)){
-		*error_out = "device number of of range";
-		return(0);
+		*error_out = "device number out of range";
+		return 0;
 	}
 
 	line = &lines[dev];
 
-	down(&line->sem);
+	spin_lock(&line->lock);
 	if(!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if(line->count == 0)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-	up(&line->sem);
+	spin_unlock(&line->lock);
 
-	return(n);
+	return n;
 }
 
-int line_remove(struct line *lines, int num, char *str)
+int line_remove(struct line *lines, unsigned int num, char *str)
 {
 	char config[sizeof("conxxxx=none\0")];
 
 	sprintf(config, "%s=none", str);
-	return(!line_setup(lines, num, config, 0));
-}
-
-int line_write_room(struct tty_struct *tty)
-{
-	struct line *dev = tty->driver_data;
-	int room;
-
-	if (tty->stopped)
-		return 0;
-	room = write_room(dev);
-	if (0 == room)
-		printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
-		       __FUNCTION__,tty->name);
-	return room;
+	return !line_setup(lines, num, config, 0);
 }
 
 struct tty_driver *line_register_devfs(struct lines *set,
@@ -553,7 +658,7 @@
 	for(i = 0; i < nlines; i++){
 		line = &lines[i];
 		INIT_LIST_HEAD(&line->chan_list);
-		sema_init(&line->sem, 1);
+		spin_lock_init(&line->lock);
 		if(line->init_str != NULL){
 			line->init_str = uml_strdup(line->init_str);
 			if(line->init_str == NULL)
@@ -587,7 +692,7 @@
 				       "errno = %d\n", -err);
 				printk("fd %d is losing SIGWINCH support\n",
 				       winch->tty_fd);
-				return(IRQ_HANDLED);
+				return IRQ_HANDLED;
 			}
 			goto out;
 		}
@@ -603,7 +708,7 @@
  out:
 	if(winch->fd != -1)
 		reactivate_fd(winch->fd, WINCH_IRQ);
-	return(IRQ_HANDLED);
+	return IRQ_HANDLED;
 }
 
 DECLARE_MUTEX(winch_handler_sem);
@@ -625,7 +730,7 @@
 				   .pid  	= pid,
 				   .tty 	= tty });
 	list_add(&winch->list, &winch_handlers);
-	if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 
+	if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
 			  SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
 			  "winch", winch) < 0)
 		printk("register_winch_irq - failed to register IRQ\n");
@@ -633,6 +738,34 @@
 	up(&winch_handler_sem);
 }
 
+static void unregister_winch(struct tty_struct *tty)
+{
+	struct list_head *ele;
+	struct winch *winch, *found = NULL;
+
+	down(&winch_handler_sem);
+	list_for_each(ele, &winch_handlers){
+		winch = list_entry(ele, struct winch, list);
+                if(winch->tty == tty){
+                        found = winch;
+                        break;
+                }
+        }
+
+        if(found == NULL)
+                goto out;
+
+        if(winch->pid != -1)
+                os_kill_process(winch->pid, 1);
+
+        free_irq_by_irq_and_dev(WINCH_IRQ, winch);
+        free_irq(WINCH_IRQ, winch);
+        list_del(&winch->list);
+        kfree(winch);
+ out:
+	up(&winch_handler_sem);
+}
+
 static void winch_cleanup(void)
 {
 	struct list_head *ele;
@@ -656,26 +789,16 @@
 	int len;
 
 	umid = get_umid(1);
-	if(umid == NULL) return(base);
+	if(umid == NULL)
+		return base;
 	
 	len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
 	title = kmalloc(len, GFP_KERNEL);
 	if(title == NULL){
 		printk("Failed to allocate buffer for xterm title\n");
-		return(base);
+		return base;
 	}
 
 	snprintf(title, len, "%s (%s)", base, umid);
-	return(title);
+	return title;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index c5839c3..a2bac42 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -107,11 +107,6 @@
 }
 
 #if 0
-static int ssl_chars_in_buffer(struct tty_struct *tty)
-{
-	return(0);
-}
-
 static void ssl_flush_buffer(struct tty_struct *tty)
 {
 	return;
@@ -149,11 +144,11 @@
 	.put_char 		= line_put_char,
 	.write_room		= line_write_room,
 	.chars_in_buffer 	= line_chars_in_buffer,
+	.flush_buffer 		= line_flush_buffer,
+	.flush_chars 		= line_flush_chars,
 	.set_termios 		= line_set_termios,
 	.ioctl 	 		= line_ioctl,
 #if 0
-	.flush_chars 		= ssl_flush_chars,
-	.flush_buffer 		= ssl_flush_buffer,
 	.throttle 		= ssl_throttle,
 	.unthrottle 		= ssl_unthrottle,
 	.stop 	 		= ssl_stop,
@@ -171,10 +166,11 @@
 			      unsigned len)
 {
 	struct line *line = &serial_lines[c->index];
+	unsigned long flags;
 
-	down(&line->sem);
+	spin_lock_irqsave(&line->lock, flags);
 	console_write_chan(&line->chan_list, string, len);
-	up(&line->sem);
+	spin_unlock_irqrestore(&line->lock, flags);
 }
 
 static struct tty_driver *ssl_console_device(struct console *c, int *index)
@@ -238,14 +234,3 @@
 
 __setup("ssl", ssl_chan_setup);
 __channel_help(ssl_chan_setup, "ssl");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index e604d7c..361d0be 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -116,8 +116,11 @@
 	.open 	 		= con_open,
 	.close 	 		= line_close,
 	.write 	 		= line_write,
+	.put_char 		= line_put_char,
  	.write_room		= line_write_room,
 	.chars_in_buffer 	= line_chars_in_buffer,
+	.flush_buffer 		= line_flush_buffer,
+	.flush_chars 		= line_flush_chars,
 	.set_termios 		= line_set_termios,
 	.ioctl 	 		= line_ioctl,
 };
@@ -126,10 +129,11 @@
 			  unsigned len)
 {
 	struct line *line = &vts[console->index];
+	unsigned long flags;
 
-	down(&line->sem);
+	spin_lock_irqsave(&line->lock, flags);
 	console_write_chan(&line->chan_list, string, len);
-	up(&line->sem);
+	spin_unlock_irqrestore(&line->lock, flags);
 }
 
 static struct tty_driver *uml_console_device(struct console *c, int *index)
@@ -192,14 +196,3 @@
 }
 __setup("con", console_chan_setup);
 __channel_help(console_chan_setup, "con");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 4d8b165..9a56ff9 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -156,6 +156,7 @@
 static struct openflags global_openflags = OPEN_FLAGS;
 
 struct cow {
+	/* This is the backing file, actually */
 	char *file;
 	int fd;
 	unsigned long *bitmap;
@@ -927,10 +928,14 @@
 		}
 	}
 	dev->count++;
-	if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
+	set_disk_ro(disk, !dev->openflags.w);
+
+	/* This should no more be needed. And it didn't work anyway to exclude
+	 * read-write remounting of filesystems.*/
+	/*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
 	        if(--dev->count == 0) ubd_close(dev);
 	        err = -EROFS;
-	}
+	}*/
  out:
 	return(err);
 }
@@ -1096,6 +1101,7 @@
 
 	if(req->rq_status == RQ_INACTIVE) return(1);
 
+	/* This should be impossible now */
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
 		printk("Write attempted on readonly ubd device %s\n", 
 		       disk->disk_name);
@@ -1243,6 +1249,7 @@
 
 		/* It's a write to a ubd device */
 
+		/* This should be impossible now */
 		if(!dev->openflags.w){
 			/* It's a write access on a read-only device - probably
 			 * shouldn't happen.  If the kernel is trying to change
@@ -1605,8 +1612,7 @@
 				}
 			} while((n < len) && (n != 0));
 			if (n < len) memset(&buf[n], 0, len - n);
-		}
-		else {
+		} else {
 			n = os_write_file(req->fds[bit], buf, len);
 			if(n != len){
 				printk("do_io - write failed err = %d "
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index 7917b9d..a4fdf35 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -7,7 +7,6 @@
 #include "linux/slab.h"
 #include "linux/signal.h"
 #include "linux/interrupt.h"
-#include "asm/semaphore.h"
 #include "asm/irq.h"
 #include "irq_user.h"
 #include "irq_kern.h"
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
new file mode 100644
index 0000000..d705daa
--- /dev/null
+++ b/arch/um/include/common-offsets.h
@@ -0,0 +1,14 @@
+/* for use by sys-$SUBARCH/kernel-offsets.c */
+
+OFFSET(TASK_REGS, task_struct, thread.regs);
+OFFSET(TASK_PID, task_struct, pid);
+DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
+DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
+DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
+DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
+DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
+DEFINE_STR(UM_KERN_ERR, KERN_ERR);
+DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
+DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
+DEFINE_STR(UM_KERN_INFO, KERN_INFO);
+DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 15389c8..e5fec55 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -8,6 +8,7 @@
 
 #include "linux/threads.h"
 #include "sysdep/ptrace.h"
+#include "sysdep/faultinfo.h"
 
 extern int ncpus;
 extern char *linux_prog;
@@ -31,8 +32,8 @@
 extern unsigned long alloc_stack(int order, int atomic);
 extern int do_signal(void);
 extern int is_stack_fault(unsigned long sp);
-extern unsigned long segv(unsigned long address, unsigned long ip, 
-			  int is_write, int is_user, void *sc);
+extern unsigned long segv(struct faultinfo fi, unsigned long ip,
+			  int is_user, void *sc);
 extern int handle_page_fault(unsigned long address, unsigned long ip,
 			     int is_write, int is_user, int *code_out);
 extern void syscall_ready(void);
@@ -82,7 +83,7 @@
 extern void unprotect_stack(unsigned long stack);
 extern void do_uml_exitcalls(void);
 extern int attach_debugger(int idle_pid, int pid, int stop);
-extern void bad_segv(unsigned long address, unsigned long ip, int is_write);
+extern void bad_segv(struct faultinfo fi, unsigned long ip);
 extern int config_gdb(char *str);
 extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 6d81ecc..4c5e92c 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -10,7 +10,7 @@
 #include "linux/workqueue.h"
 #include "linux/tty.h"
 #include "linux/interrupt.h"
-#include "asm/semaphore.h"
+#include "linux/spinlock.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
@@ -37,10 +37,18 @@
 	struct list_head chan_list;
 	int valid;
 	int count;
-	struct semaphore sem;
+	/*This lock is actually, mostly, local to*/
+	spinlock_t lock;
+
+	/* Yes, this is a real circular buffer.
+	 * XXX: And this should become a struct kfifo!
+	 *
+	 * buffer points to a buffer allocated on demand, of length
+	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
 	char *buffer;
 	char *head;
 	char *tail;
+
 	int sigio;
 	struct work_struct task;
 	struct line_driver *driver;
@@ -52,7 +60,6 @@
 	  init_pri :	INIT_STATIC, \
 	  chan_list : 	{ }, \
 	  valid :	1, \
-	  sem : 	{ }, \
 	  buffer :	NULL, \
 	  head :	NULL, \
 	  tail :	NULL, \
@@ -69,15 +76,18 @@
 extern void line_close(struct tty_struct *tty, struct file * filp);
 extern int line_open(struct line *lines, struct tty_struct *tty, 
 		     struct chan_opts *opts);
-extern int line_setup(struct line *lines, int num, char *init, 
+extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init,
 		      int all_allowed);
 extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len);
 extern void line_put_char(struct tty_struct *tty, unsigned char ch);
 extern void line_set_termios(struct tty_struct *tty, struct termios * old);
 extern int line_chars_in_buffer(struct tty_struct *tty);
+extern void line_flush_buffer(struct tty_struct *tty);
+extern void line_flush_chars(struct tty_struct *tty);
 extern int line_write_room(struct tty_struct *tty);
 extern int line_ioctl(struct tty_struct *tty, struct file * file,
 		      unsigned int cmd, unsigned long arg);
+
 extern char *add_xterm_umid(char *base);
 extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty);
 extern void line_close_chan(struct line *line);
@@ -89,20 +99,10 @@
 				int nlines);
 extern void lines_init(struct line *lines, int nlines);
 extern void close_lines(struct line *lines, int nlines);
-extern int line_config(struct line *lines, int num, char *str);
-extern int line_remove(struct line *lines, int num, char *str);
-extern int line_get_config(char *dev, struct line *lines, int num, char *str, 
+
+extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str);
+extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
 			   int size, char **error_out);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 07340c8..d246d5a 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -160,6 +160,7 @@
 extern void os_kill_ptraced_process(int pid, int reap_child);
 extern void os_usr1_process(int pid);
 extern int os_getpid(void);
+extern int os_getpgrp(void);
 
 extern int os_map_memory(void *virt, int fd, unsigned long long off,
 			 unsigned long len, int r, int w, int x);
diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h
index cfb5fb4..cd2327d 100644
--- a/arch/um/include/skas_ptrace.h
+++ b/arch/um/include/skas_ptrace.h
@@ -6,22 +6,11 @@
 #ifndef __SKAS_PTRACE_H
 #define __SKAS_PTRACE_H
 
-struct ptrace_faultinfo {
-	int is_write;
-	unsigned long addr;
-};
-
-struct ptrace_ldt {
-	int func;
-  	void *ptr;
-	unsigned long bytecount;
-};
-
 #define PTRACE_FAULTINFO 52
-#define PTRACE_SIGPENDING 53
-#define PTRACE_LDT 54
 #define PTRACE_SWITCH_MM 55
 
+#include "sysdep/skas_ptrace.h"
+
 #endif
 
 /*
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 3a2a458..764ba4d 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -24,19 +24,6 @@
 			  unsigned int sum);
 
 /*
- * the same as csum_partial, but copies from src while it
- * checksums, and handles user-space pointer exceptions correctly, when needed.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-unsigned int csum_partial_copy_to(const unsigned char *src, unsigned char *dst,
-				  int len, int sum, int *err_ptr);
-unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst,
-				    int len, int sum, int *err_ptr);
-
-/*
  *	Note: when you get a NULL pointer exception here this means someone
  *	passed in an incorrect kernel address to one of these functions.
  *
@@ -52,11 +39,24 @@
 	return(csum_partial(dst, len, sum));
 }
 
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
 static __inline__
 unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
 					 int len, int sum, int *err_ptr)
 {
-	return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+	if(copy_from_user(dst, src, len)){
+		*err_ptr = -EFAULT;
+		return(-1);
+	}
+
+	return csum_partial(dst, len, sum);
 }
 
 /*
@@ -67,7 +67,6 @@
  */
 
 #define csum_partial_copy_fromuser csum_partial_copy_from_user
-unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst, int len, int sum);
 
 /*
  *	This is a version of ip_compute_csum() optimized for IP headers,
@@ -196,8 +195,14 @@
 						     unsigned char *dst,
 						     int len, int sum, int *err_ptr)
 {
-	if (access_ok(VERIFY_WRITE, dst, len))
-		return(csum_partial_copy_to(src, dst, len, sum, err_ptr));
+	if (access_ok(VERIFY_WRITE, dst, len)){
+		if(copy_to_user(dst, src, len)){
+			*err_ptr = -EFAULT;
+			return(-1);
+		}
+
+		return csum_partial(src, len, sum);
+	}
 
 	if (len)
 		*err_ptr = -EFAULT;
diff --git a/arch/um/include/sysdep-i386/faultinfo.h b/arch/um/include/sysdep-i386/faultinfo.h
new file mode 100644
index 0000000..db437cc
--- /dev/null
+++ b/arch/um/include/sysdep-i386/faultinfo.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_I386_H
+#define __FAULTINFO_I386_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+#define PTRACE_FULL_FAULTINFO 0
+
+#endif
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 661d495..84ec7ff 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -31,6 +31,7 @@
 #ifdef UML_CONFIG_MODE_SKAS
 
 #include "skas_ptregs.h"
+#include "sysdep/faultinfo.h"
 
 #define REGS_IP(r) ((r)[HOST_IP])
 #define REGS_SP(r) ((r)[HOST_SP])
@@ -53,12 +54,6 @@
 
 #define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
 
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
 #endif
 #ifndef PTRACE_SYSEMU_SINGLESTEP
 #define PTRACE_SYSEMU_SINGLESTEP 32
@@ -71,6 +66,7 @@
 	struct tt_regs {
 		long syscall;
 		void *sc;
+                struct faultinfo faultinfo;
 	} tt;
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
@@ -78,9 +74,7 @@
 		unsigned long regs[HOST_FRAME_SIZE];
 		unsigned long fp[HOST_FP_SIZE];
 		unsigned long xfp[HOST_XFP_SIZE];
-		unsigned long fault_addr;
-		unsigned long fault_type;
-		unsigned long trap_type;
+                struct faultinfo faultinfo;
 		long syscall;
 		int is_user;
 	} skas;
@@ -217,15 +211,8 @@
 #define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
 #define UPT_SYSCALL_RET(r) UPT_EAX(r)
 
-#define UPT_SEGV_IS_FIXABLE(r) \
-	CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
-                    REGS_SEGV_IS_FIXABLE(&r->skas))
-
-#define UPT_FAULT_ADDR(r) \
-	__CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
-
-#define UPT_FAULT_WRITE(r) \
-	CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
+#define UPT_FAULTINFO(r) \
+        CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
 
 #endif
 
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index dfee589..1fe7292 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -13,15 +13,12 @@
 #define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
 #define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
 
-#define SC_FAULT_ADDR(sc) SC_CR2(sc)
-#define SC_FAULT_TYPE(sc) SC_ERR(sc)
-
-#define FAULT_WRITE(err) (err & 2)
-#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0)
-
-#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc)))
-
-#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
+#define GET_FAULTINFO_FROM_SC(fi,sc) \
+	{ \
+		(fi).cr2 = SC_CR2(sc); \
+		(fi).error_code = SC_ERR(sc); \
+		(fi).trap_no = SC_TRAPNO(sc); \
+	}
 
 /* ptrace expects that, at the start of a system call, %eax contains
  * -ENOSYS, so this makes it so.
@@ -29,9 +26,7 @@
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
 /* This is Page Fault */
-#define SEGV_IS_FIXABLE(trap) (trap == 14)
-
-#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
+#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
 
 extern unsigned long *sc_sigmask(void *sc_ptr);
 extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h
index b1e1f7a..07518b1 100644
--- a/arch/um/include/sysdep-i386/signal.h
+++ b/arch/um/include/sysdep-i386/signal.h
@@ -8,6 +8,8 @@
 
 #include <signal.h>
 
+#define ARCH_SIGHDLR_PARAM int sig
+
 #define ARCH_GET_SIGCONTEXT(sc, sig) \
 	do sc = (struct sigcontext *) (&sig + 1); while(0)
 
diff --git a/arch/um/include/sysdep-i386/skas_ptrace.h b/arch/um/include/sysdep-i386/skas_ptrace.h
new file mode 100644
index 0000000..e27b8a7
--- /dev/null
+++ b/arch/um/include/sysdep-i386/skas_ptrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_I386_SKAS_PTRACE_H
+#define __SYSDEP_I386_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 5db81ec..be0a3e3 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -22,102 +22,3 @@
 extern long sys_mmap2(unsigned long addr, unsigned long len,
 		      unsigned long prot, unsigned long flags,
 		      unsigned long fd, unsigned long pgoff);
-
-/* On i386 they choose a meaningless naming.*/
-#define __NR_kexec_load __NR_sys_kexec_load
-
-#define ARCH_SYSCALLS \
-	[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \
-	[ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_oldstat ] = (syscall_handler_t *) sys_stat, \
-	[ __NR_umount ] = (syscall_handler_t *) sys_oldumount, \
-	[ __NR_stime ] = um_stime, \
-	[ __NR_oldfstat ] = (syscall_handler_t *) sys_fstat, \
-	[ __NR_stty ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_gtty ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_nice ] = (syscall_handler_t *) sys_nice, \
-	[ __NR_ftime ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_prof ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_signal ] = (syscall_handler_t *) sys_signal, \
-	[ __NR_lock ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_mpx ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_ulimit ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_oldolduname ] = (syscall_handler_t *) sys_olduname, \
-	[ __NR_sigaction ] = (syscall_handler_t *) sys_sigaction, \
-	[ __NR_sgetmask ] = (syscall_handler_t *) sys_sgetmask, \
-	[ __NR_ssetmask ] = (syscall_handler_t *) sys_ssetmask, \
-	[ __NR_sigsuspend ] = (syscall_handler_t *) sys_sigsuspend, \
-	[ __NR_sigpending ] = (syscall_handler_t *) sys_sigpending, \
-	[ __NR_oldlstat ] = (syscall_handler_t *) sys_lstat, \
-	[ __NR_readdir ] = old_readdir, \
-	[ __NR_profil ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_socketcall ] = (syscall_handler_t *) sys_socketcall, \
-	[ __NR_olduname ] = (syscall_handler_t *) sys_uname, \
-	[ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_idle ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_ipc ] = (syscall_handler_t *) sys_ipc, \
-	[ __NR_sigreturn ] = (syscall_handler_t *) sys_sigreturn, \
-	[ __NR_sigprocmask ] = (syscall_handler_t *) sys_sigprocmask, \
-	[ __NR_bdflush ] = (syscall_handler_t *) sys_bdflush, \
-	[ __NR__llseek ] = (syscall_handler_t *) sys_llseek, \
-	[ __NR__newselect ] = (syscall_handler_t *) sys_select, \
-	[ __NR_vm86 ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
-	[ __NR_ugetrlimit ] = (syscall_handler_t *) sys_getrlimit, \
-	[ __NR_mmap2 ] = (syscall_handler_t *) sys_mmap2, \
-	[ __NR_truncate64 ] = (syscall_handler_t *) sys_truncate64, \
-	[ __NR_ftruncate64 ] = (syscall_handler_t *) sys_ftruncate64, \
-	[ __NR_stat64 ] = (syscall_handler_t *) sys_stat64, \
-	[ __NR_lstat64 ] = (syscall_handler_t *) sys_lstat64, \
-	[ __NR_fstat64 ] = (syscall_handler_t *) sys_fstat64, \
-	[ __NR_fcntl64 ] = (syscall_handler_t *) sys_fcntl64, \
-	[ __NR_sendfile64 ] = (syscall_handler_t *) sys_sendfile64, \
-	[ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64, \
-	[ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64, \
-	[ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \
-	[ __NR_select ] = (syscall_handler_t *) old_select, \
-	[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
-	[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
-	[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
-	[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
-	[ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \
-	[ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \
-	[ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \
-	[ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \
-	[ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \
-	[ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \
-	[ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \
-	[ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \
-	[ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \
-	[ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \
-	[ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \
-	[ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \
-	[ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \
-	[ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \
-	[ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \
-	[ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \
-	[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
-	[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
-	[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
-	[ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ 251 ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ 285 ] = (syscall_handler_t *) sys_ni_syscall,
-
-/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-
-#define LAST_ARCH_SYSCALL 285
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/sysdep-ia64/skas_ptrace.h b/arch/um/include/sysdep-ia64/skas_ptrace.h
new file mode 100644
index 0000000..25a38e7
--- /dev/null
+++ b/arch/um/include/sysdep-ia64/skas_ptrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_IA64_SKAS_PTRACE_H
+#define __SYSDEP_IA64_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-ppc/skas_ptrace.h b/arch/um/include/sysdep-ppc/skas_ptrace.h
new file mode 100644
index 0000000..d9fbbac
--- /dev/null
+++ b/arch/um/include/sysdep-ppc/skas_ptrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_PPC_SKAS_PTRACE_H
+#define __SYSDEP_PPC_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/faultinfo.h b/arch/um/include/sysdep-x86_64/faultinfo.h
new file mode 100644
index 0000000..cb917b0
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/faultinfo.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_X86_64_H
+#define __FAULTINFO_X86_64_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+#define PTRACE_FULL_FAULTINFO 1
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 915c82d..348e8fc 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -9,6 +9,7 @@
 
 #include "uml-config.h"
 #include "user_constants.h"
+#include "sysdep/faultinfo.h"
 
 #define MAX_REG_OFFSET (UM_FRAME_SIZE)
 #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
@@ -83,6 +84,7 @@
 		long syscall;
 		unsigned long orig_rax;
 		void *sc;
+                struct faultinfo faultinfo;
 	} tt;
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
@@ -90,9 +92,7 @@
 		/* XXX */
 		unsigned long regs[27];
 		unsigned long fp[65];
-		unsigned long fault_addr;
-		unsigned long fault_type;
-		unsigned long trap_type;
+                struct faultinfo faultinfo;
 		long syscall;
 		int is_user;
 	} skas;
@@ -241,14 +241,8 @@
 	CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
                     REGS_SEGV_IS_FIXABLE(&r->skas))
 
-#define UPT_FAULT_ADDR(r) \
-	__CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
-
-#define UPT_FAULT_WRITE(r) \
-	CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
-
-#define UPT_TRAP(r) __CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas))
-#define UPT_ERR(r) __CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas))
+#define UPT_FAULTINFO(r) \
+        CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
 
 #endif
 
diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h
index 1e38a54..2a78260 100644
--- a/arch/um/include/sysdep-x86_64/sigcontext.h
+++ b/arch/um/include/sysdep-x86_64/sigcontext.h
@@ -17,11 +17,12 @@
 #define SC_FAULT_ADDR(sc) SC_CR2(sc)
 #define SC_FAULT_TYPE(sc) SC_ERR(sc)
 
-#define FAULT_WRITE(err) ((err) & 2)
-
-#define SC_FAULT_WRITE(sc) FAULT_WRITE(SC_FAULT_TYPE(sc))
-
-#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
+#define GET_FAULTINFO_FROM_SC(fi,sc) \
+	{ \
+		(fi).cr2 = SC_CR2(sc); \
+		(fi).error_code = SC_ERR(sc); \
+		(fi).trap_no = SC_TRAPNO(sc); \
+	}
 
 /* ptrace expects that, at the start of a system call, %eax contains
  * -ENOSYS, so this makes it so.
@@ -29,8 +30,8 @@
 
 #define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0)
 
-#define SEGV_IS_FIXABLE(trap) ((trap) == 14)
-#define SC_SEGV_IS_FIXABLE(sc) SEGV_IS_FIXABLE(SC_TRAP_TYPE(sc))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
 
 extern unsigned long *sc_sigmask(void *sc_ptr);
 
diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h
index e5e5275..6142897 100644
--- a/arch/um/include/sysdep-x86_64/signal.h
+++ b/arch/um/include/sysdep-x86_64/signal.h
@@ -6,6 +6,8 @@
 #ifndef __X86_64_SIGNAL_H_
 #define __X86_64_SIGNAL_H_
 
+#define ARCH_SIGHDLR_PARAM int sig
+
 #define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
 	do { \
 		struct ucontext *__uc; \
diff --git a/arch/um/include/sysdep-x86_64/skas_ptrace.h b/arch/um/include/sysdep-x86_64/skas_ptrace.h
new file mode 100644
index 0000000..95db4be7
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/skas_ptrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
+#define __SYSDEP_X86_64_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index b187a41..67923cc 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -26,66 +26,9 @@
 extern long old_mmap(unsigned long addr, unsigned long len,
 		     unsigned long prot, unsigned long flags,
 		     unsigned long fd, unsigned long pgoff);
-extern syscall_handler_t wrap_sys_shmat;
 extern syscall_handler_t sys_modify_ldt;
 extern syscall_handler_t sys_arch_prctl;
 
-#define ARCH_SYSCALLS \
-	[ __NR_mmap ] = (syscall_handler_t *) old_mmap, \
-	[ __NR_select ] = (syscall_handler_t *) sys_select, \
-	[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
-	[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
-	[ __NR_shmget ] = (syscall_handler_t *) sys_shmget, \
-	[ __NR_shmat ] = (syscall_handler_t *) wrap_sys_shmat, \
-	[ __NR_shmctl ] = (syscall_handler_t *) sys_shmctl, \
-	[ __NR_semop ] = (syscall_handler_t *) sys_semop, \
-	[ __NR_semget ] = (syscall_handler_t *) sys_semget, \
-	[ __NR_semctl ] = (syscall_handler_t *) sys_semctl, \
-	[ __NR_shmdt ] = (syscall_handler_t *) sys_shmdt, \
-	[ __NR_msgget ] = (syscall_handler_t *) sys_msgget, \
-	[ __NR_msgsnd ] = (syscall_handler_t *) sys_msgsnd, \
-	[ __NR_msgrcv ] = (syscall_handler_t *) sys_msgrcv, \
-	[ __NR_msgctl ] = (syscall_handler_t *) sys_msgctl, \
-	[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
-	[ __NR_tuxcall ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_security ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_epoll_ctl_old ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_epoll_wait_old ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
-	[ __NR_arch_prctl ] = (syscall_handler_t *) sys_arch_prctl, \
-	[ __NR_socket ] = (syscall_handler_t *) sys_socket, \
-	[ __NR_connect ] = (syscall_handler_t *) sys_connect, \
-	[ __NR_accept ] = (syscall_handler_t *) sys_accept, \
-	[ __NR_recvfrom ] = (syscall_handler_t *) sys_recvfrom, \
-	[ __NR_recvmsg ] = (syscall_handler_t *) sys_recvmsg, \
-	[ __NR_sendmsg ] = (syscall_handler_t *) sys_sendmsg, \
-	[ __NR_bind ] = (syscall_handler_t *) sys_bind, \
-	[ __NR_listen ] = (syscall_handler_t *) sys_listen, \
-	[ __NR_getsockname ] = (syscall_handler_t *) sys_getsockname, \
-	[ __NR_getpeername ] = (syscall_handler_t *) sys_getpeername, \
-	[ __NR_socketpair ] = (syscall_handler_t *) sys_socketpair, \
-	[ __NR_sendto ] = (syscall_handler_t *) sys_sendto, \
-	[ __NR_shutdown ] = (syscall_handler_t *) sys_shutdown, \
-	[ __NR_setsockopt ] = (syscall_handler_t *) sys_setsockopt, \
-	[ __NR_getsockopt ] = (syscall_handler_t *) sys_getsockopt, \
-	[ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
-	[ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \
-	[ 251 ] = (syscall_handler_t *) sys_ni_syscall,
-
-#define LAST_ARCH_SYSCALL 251
-#define NR_syscalls 1024
+#define NR_syscalls (__NR_syscall_max + 1)
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 103cd32..b8c5b8a 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -67,7 +67,6 @@
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(void);
-extern void add_arg(char *arg);
 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
 extern void init_new_thread_signals(int altstack);
 extern void do_exec(int old_pid, int new_pid);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index dc796c1..9736ca2 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -4,13 +4,13 @@
 #
 
 extra-y := vmlinux.lds
-clean-files := vmlinux.lds.S config.tmp
+clean-files :=
 
-obj-y = checksum.o config.o exec_kern.o exitcode.o \
+obj-y = config.o exec_kern.o exitcode.o \
 	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
 	physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
 	sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
-	syscall_kern.o sysrq.o sys_call_table.o tempfile.o time.o time_kern.o \
+	syscall_kern.o sysrq.o tempfile.o time.o time_kern.o \
 	tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
 	user_util.o
 
@@ -23,18 +23,14 @@
 obj-$(CONFIG_MODE_TT) += tt/
 obj-$(CONFIG_MODE_SKAS) += skas/
 
-# This needs be compiled with frame pointers regardless of how the rest of the
-# kernel is built.
-CFLAGS_frame.o := -fno-omit-frame-pointer
-
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(user-objs-y) config.o helper.o main.o process.o tempfile.o \
-	time.o tty_log.o umid.o user_util.o frame.o
+	time.o tty_log.o umid.o user_util.o
 
 include arch/um/scripts/Makefile.rules
 
-targets += config.c
+targets := config.c config.tmp
 
 # Be careful with the below Sed code - sed is pitfall-rich!
 # We use sed to lower build requirements, for "embedded" builders for instance.
@@ -53,6 +49,7 @@
       cmd_quote2 = sed -e '/CONFIG/{'          \
 		  -e 's/"CONFIG"\;/""/'        \
 		  -e 'r $(obj)/config.tmp'     \
-		  -e 'a""\;'                   \
+		  -e 'a \'                     \
+		  -e '""\;'                    \
 		  -e '}'                       \
 		  $< > $@
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
index e69b2be..e69de29 100644
--- a/arch/um/kernel/checksum.c
+++ b/arch/um/kernel/checksum.c
@@ -1,36 +0,0 @@
-#include "asm/uaccess.h"
-#include "linux/errno.h"
-#include "linux/module.h"
-
-unsigned int arch_csum_partial(const unsigned char *buff, int len, int sum);
-
-unsigned int csum_partial(unsigned char *buff, int len, int sum)
-{
-        return arch_csum_partial(buff, len, sum);
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-unsigned int csum_partial_copy_to(const unsigned char *src,
-                                  unsigned char __user *dst, int len, int sum,
-                                  int *err_ptr)
-{
-        if(copy_to_user(dst, src, len)){
-                *err_ptr = -EFAULT;
-                return(-1);
-        }
-
-        return(arch_csum_partial(src, len, sum));
-}
-
-unsigned int csum_partial_copy_from(const unsigned char __user *src,
-                                    unsigned char *dst,	int len, int sum,
-                                    int *err_ptr)
-{
-        if(copy_from_user(dst, src, len)){
-                *err_ptr = -EFAULT;
-                return(-1);
-        }
-
-        return arch_csum_partial(dst, len, sum);
-}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index d71e8f0..d44fb52 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -163,7 +163,6 @@
 		irq_desc[i].handler = &SIGIO_irq_type;
 		enable_irq(i);
 	}
-	init_irq_signals(0);
 }
 
 /*
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index b41d339..78d69dc 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -10,7 +10,6 @@
 #include "linux/spinlock.h"
 #include "linux/highmem.h"
 #include "asm/current.h"
-#include "asm/delay.h"
 #include "asm/processor.h"
 #include "asm/unistd.h"
 #include "asm/pgalloc.h"
@@ -28,8 +27,6 @@
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(sys_waitpid);
 EXPORT_SYMBOL(task_size);
 EXPORT_SYMBOL(flush_tlb_range);
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index f76a269..51f8e5a 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -65,8 +65,6 @@
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, 
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-	set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, 
-		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
 		    flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	signal(SIGHUP, SIG_IGN);
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 1d719d5..c1adf7b 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -115,16 +115,6 @@
 	return(pid);
 }
 
-void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
-	       struct task_struct *tsk)
-{
-	int cpu = smp_processor_id();
-
-	if (prev != next) 
-		cpu_clear(cpu, prev->cpu_vm_mask);
-	cpu_set(cpu, next->cpu_vm_mask);
-}
-
 void set_current(void *t)
 {
 	struct task_struct *task = t;
@@ -152,7 +142,6 @@
  
 void exit_thread(void)
 {
-	CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
 	unprotect_stack((unsigned long) current_thread);
 }
  
@@ -161,10 +150,6 @@
 	return(current);
 }
 
-void prepare_to_copy(struct task_struct *tsk)
-{
-}
-
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		unsigned long stack_top, struct task_struct * p, 
 		struct pt_regs *regs)
@@ -480,12 +465,21 @@
 	return 2;
 }
 
+/*
+ * Only x86 and x86_64 have an arch_align_stack().
+ * All other arches have "#define arch_align_stack(x) (x)"
+ * in their asm/system.h
+ * As this is included in UML from asm-um/system-generic.h,
+ * we can use it to behave as the subarch does.
+ */
+#ifndef arch_align_stack
 unsigned long arch_align_stack(unsigned long sp)
 {
 	if (randomize_va_space)
 		sp -= get_random_int() % 8192;
 	return sp & ~0xf;
 }
+#endif
 
 
 /*
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 3a99ee6..2b75d8d 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -19,15 +19,30 @@
 #include "skas_ptrace.h"
 #include "sysdep/ptrace.h"
 
+static inline void set_singlestepping(struct task_struct *child, int on)
+{
+        if (on)
+                child->ptrace |= PT_DTRACE;
+        else
+                child->ptrace &= ~PT_DTRACE;
+        child->thread.singlestep_syscall = 0;
+
+#ifdef SUBARCH_SET_SINGLESTEPPING
+        SUBARCH_SET_SINGLESTEPPING(child, on)
+#endif
+                }
+
 /*
  * Called by kernel/ptrace.c when detaching..
  */
 void ptrace_disable(struct task_struct *child)
 { 
-	child->ptrace &= ~PT_DTRACE;
-	child->thread.singlestep_syscall = 0;
+        set_singlestepping(child,0);
 }
 
+extern int peek_user(struct task_struct * child, long addr, long data);
+extern int poke_user(struct task_struct * child, long addr, long data);
+
 long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -67,6 +82,10 @@
 		goto out_tsk;
 	}
 
+#ifdef SUBACH_PTRACE_SPECIAL
+        SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
+#endif
+
 	ret = ptrace_check_attach(child, request == PTRACE_KILL);
 	if (ret < 0)
 		goto out_tsk;
@@ -87,26 +106,9 @@
 	}
 
 	/* read the word at location addr in the USER area. */
-	case PTRACE_PEEKUSR: {
-		unsigned long tmp;
-
-		ret = -EIO;
-		if ((addr & 3) || addr < 0) 
-			break;
-
-		tmp = 0;  /* Default return condition */
-		if(addr < MAX_REG_OFFSET){
-			tmp = getreg(child, addr);
-		}
-		else if((addr >= offsetof(struct user, u_debugreg[0])) &&
-			(addr <= offsetof(struct user, u_debugreg[7]))){
-			addr -= offsetof(struct user, u_debugreg[0]);
-			addr = addr >> 2;
-			tmp = child->thread.arch.debugregs[addr];
-		}
-		ret = put_user(tmp, (unsigned long __user *) data);
-		break;
-	}
+        case PTRACE_PEEKUSR:
+                ret = peek_user(child, addr, data);
+                break;
 
 	/* when I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
@@ -119,35 +121,16 @@
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-		ret = -EIO;
-		if ((addr & 3) || addr < 0)
-			break;
-
-		if (addr < MAX_REG_OFFSET) {
-			ret = putreg(child, addr, data);
-			break;
-		}
-#if 0 /* XXX x86_64 */
-		else if((addr >= offsetof(struct user, u_debugreg[0])) &&
-			(addr <= offsetof(struct user, u_debugreg[7]))){
-			  addr -= offsetof(struct user, u_debugreg[0]);
-			  addr = addr >> 2;
-			  if((addr == 4) || (addr == 5)) break;
-			  child->thread.arch.debugregs[addr] = data;
-			  ret = 0;
-		}
-#endif
-
-		break;
+                ret = poke_user(child, addr, data);
+                break;
 
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 
-		child->ptrace &= ~PT_DTRACE;
-		child->thread.singlestep_syscall = 0;
+                set_singlestepping(child, 0);
 		if (request == PTRACE_SYSCALL) {
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		}
@@ -170,8 +153,7 @@
 		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
 			break;
 
-		child->ptrace &= ~PT_DTRACE;
-		child->thread.singlestep_syscall = 0;
+                set_singlestepping(child, 0);
 		child->exit_code = SIGKILL;
 		wake_up_process(child);
 		break;
@@ -179,11 +161,10 @@
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->ptrace |= PT_DTRACE;
-		child->thread.singlestep_syscall = 0;
+                set_singlestepping(child, 1);
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -250,23 +231,19 @@
 		break;
 #endif
 	case PTRACE_FAULTINFO: {
-		struct ptrace_faultinfo fault;
-
-		fault = ((struct ptrace_faultinfo) 
-			{ .is_write	= child->thread.err,
-			  .addr		= child->thread.cr2 });
-		ret = copy_to_user((unsigned long __user *) data, &fault,
-				   sizeof(fault));
+                /* Take the info from thread->arch->faultinfo,
+                 * but transfer max. sizeof(struct ptrace_faultinfo).
+                 * On i386, ptrace_faultinfo is smaller!
+                 */
+                ret = copy_to_user((unsigned long __user *) data,
+                                   &child->thread.arch.faultinfo,
+                                   sizeof(struct ptrace_faultinfo));
 		if(ret)
 			break;
 		break;
 	}
-	case PTRACE_SIGPENDING:
-		ret = copy_to_user((unsigned long __user *) data,
-				   &child->pending.signal,
-				   sizeof(child->pending.signal));
-		break;
 
+#ifdef PTRACE_LDT
 	case PTRACE_LDT: {
 		struct ptrace_ldt ldt;
 
@@ -282,6 +259,7 @@
 		ret = -EIO;
 		break;
 	}
+#endif
 #ifdef CONFIG_PROC_MM
 	case PTRACE_SWITCH_MM: {
 		struct mm_struct *old = child->mm;
@@ -337,15 +315,18 @@
 
 	if (unlikely(current->audit_context)) {
 		if (!entryexit)
-			audit_syscall_entry(current, 
-					    UPT_SYSCALL_NR(&regs->regs),
-					    UPT_SYSCALL_ARG1(&regs->regs),
-					    UPT_SYSCALL_ARG2(&regs->regs),
-					    UPT_SYSCALL_ARG3(&regs->regs),
-					    UPT_SYSCALL_ARG4(&regs->regs));
-		else
-			audit_syscall_exit(current, 
-					   UPT_SYSCALL_RET(&regs->regs));
+			audit_syscall_entry(current,
+                                            HOST_AUDIT_ARCH,
+					    UPT_SYSCALL_NR(regs),
+					    UPT_SYSCALL_ARG1(regs),
+					    UPT_SYSCALL_ARG2(regs),
+					    UPT_SYSCALL_ARG3(regs),
+					    UPT_SYSCALL_ARG4(regs));
+		else {
+                        int res = UPT_SYSCALL_RET(regs);
+			audit_syscall_exit(current, AUDITSC_RESULT(res),
+                                           res);
+                }
 	}
 
 	/* Fake a debug trap */
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 668df13..e892189 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -182,6 +182,7 @@
 	int i, n, respond_fd;
 	char c;
 
+        signal(SIGWINCH, SIG_IGN);
 	fds = &current_poll;
 	while(1){
 		n = poll(fds->poll, fds->used, -1);
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
index 94c5649..e484900 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/kernel/skas/include/mode_kern-skas.h
@@ -18,7 +18,6 @@
 			    unsigned long sp, unsigned long stack_top,
 			    struct task_struct *p, struct pt_regs *regs);
 extern void release_thread_skas(struct task_struct *task);
-extern void exit_thread_skas(void);
 extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
 extern void init_idle_skas(void);
 extern void flush_tlb_kernel_range_skas(unsigned long start,
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index f0702c2..96b51db 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -27,9 +27,10 @@
 extern int unmap(int fd, void *addr, unsigned long len);
 extern int protect(int fd, unsigned long addr, unsigned long len, 
 		   int r, int w, int x);
-extern void user_signal(int sig, union uml_pt_regs *regs);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
 extern int new_mm(int from);
 extern void start_userspace(int cpu);
+extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
 extern long execute_syscall_skas(void *r);
 
 #endif
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
index 11986c9..cd6c280 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/kernel/skas/include/uaccess-skas.h
@@ -19,7 +19,7 @@
 	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
 
 static inline int verify_area_skas(int type, const void * addr,
-				   unsigned long size)
+                                   unsigned long size)
 {
 	return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
 }
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index b4ffaaa..773cd2b 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -4,6 +4,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include <signal.h>
@@ -27,27 +28,37 @@
 #include "chan_user.h"
 #include "signal_user.h"
 #include "registers.h"
+#include "process.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-	if(pid != os_getpid())
+        if(pid != os_getpgrp())
 		return(0);
 
 	register_winch_irq(-1, fd, -1, data);
 	return(1);
 }
 
-static void handle_segv(int pid)
+void get_skas_faultinfo(int pid, struct faultinfo * fi)
 {
-	struct ptrace_faultinfo fault;
 	int err;
 
-	err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault);
+        err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
 	if(err)
-		panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n",
-		      errno);
+                panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
+                      "errno = %d\n", errno);
 
-	segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
+        /* Special handling for i386, which has different structs */
+        if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
+                memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
+                       sizeof(struct faultinfo) -
+                       sizeof(struct ptrace_faultinfo));
+}
+
+static void handle_segv(int pid, union uml_pt_regs * regs)
+{
+        get_skas_faultinfo(pid, &regs->skas.faultinfo);
+        segv(regs->skas.faultinfo, 0, 1, NULL);
 }
 
 /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
@@ -163,7 +174,7 @@
 		if(WIFSTOPPED(status)){
 		  	switch(WSTOPSIG(status)){
 			case SIGSEGV:
-				handle_segv(pid);
+                                handle_segv(pid, regs);
 				break;
 			case SIGTRAP + 0x80:
 			        handle_trap(pid, regs, local_using_sysemu);
@@ -177,7 +188,7 @@
 			case SIGBUS:
 			case SIGFPE:
 			case SIGWINCH:
-				user_signal(WSTOPSIG(status), regs);
+                                user_signal(WSTOPSIG(status), regs, pid);
 				break;
 			default:
 			        printk("userspace - child stopped with signal "
@@ -190,6 +201,11 @@
 		}
 	}
 }
+#define INIT_JMP_NEW_THREAD 0
+#define INIT_JMP_REMOVE_SIGSTACK 1
+#define INIT_JMP_CALLBACK 2
+#define INIT_JMP_HALT 3
+#define INIT_JMP_REBOOT 4
 
 void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
 		void (*handler)(int))
@@ -225,7 +241,7 @@
 	*switch_buf = &buf;
 	fork_buf = fb;
 	if(sigsetjmp(buf, 1) == 0)
-		siglongjmp(*fork_buf, 1);
+		siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
 }
 
 void switch_threads(void *me, void *next)
@@ -249,23 +265,31 @@
 	sigjmp_buf **switch_buf = switch_buf_ptr;
 	int n;
 
+	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
+		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
+		    SIGVTALRM, -1);
+
 	*fork_buf_ptr = &initial_jmpbuf;
 	n = sigsetjmp(initial_jmpbuf, 1);
-	if(n == 0)
-		new_thread_proc((void *) stack, new_thread_handler);
-	else if(n == 1)
-		remove_sigstack();
-	else if(n == 2){
+        switch(n){
+        case INIT_JMP_NEW_THREAD:
+                new_thread_proc((void *) stack, new_thread_handler);
+                break;
+        case INIT_JMP_REMOVE_SIGSTACK:
+                remove_sigstack();
+                break;
+        case INIT_JMP_CALLBACK:
 		(*cb_proc)(cb_arg);
 		siglongjmp(*cb_back, 1);
-	}
-	else if(n == 3){
+                break;
+        case INIT_JMP_HALT:
 		kmalloc_ok = 0;
 		return(0);
-	}
-	else if(n == 4){
+        case INIT_JMP_REBOOT:
 		kmalloc_ok = 0;
 		return(1);
+        default:
+                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
 	}
 	siglongjmp(**switch_buf, 1);
 }
@@ -290,7 +314,7 @@
 
 	block_signals();
 	if(sigsetjmp(here, 1) == 0)
-		siglongjmp(initial_jmpbuf, 2);
+		siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -301,13 +325,13 @@
 void halt_skas(void)
 {
 	block_signals();
-	siglongjmp(initial_jmpbuf, 3);
+	siglongjmp(initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	siglongjmp(initial_jmpbuf, 4);
+	siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
 void switch_mm_skas(int mm_fd)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 5d096ea..ab5d327 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -83,10 +83,6 @@
 {
 }
 
-void exit_thread_skas(void)
-{
-}
-
 void fork_handler(int sig)
 {
         change_sig(SIGUSR1, 1);
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
index 8e9b46d..0dee1d9 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/kernel/skas/trap_user.c
@@ -5,12 +5,15 @@
 
 #include <signal.h>
 #include <errno.h>
-#include "sysdep/ptrace.h"
 #include "signal_user.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "task.h"
 #include "sigcontext.h"
+#include "skas.h"
+#include "ptrace_user.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/ptrace_user.h"
 
 void sig_handler_common_skas(int sig, void *sc_ptr)
 {
@@ -31,9 +34,11 @@
 	r = &TASK_REGS(get_current())->skas;
 	save_user = r->is_user;
 	r->is_user = 0;
-	r->fault_addr = SC_FAULT_ADDR(sc);
-	r->fault_type = SC_FAULT_TYPE(sc);
-	r->trap_type = SC_TRAP_TYPE(sc);
+        if ( sig == SIGFPE || sig == SIGSEGV ||
+             sig == SIGBUS || sig == SIGILL ||
+             sig == SIGTRAP ) {
+                GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
+        }
 
 	change_sig(SIGUSR1, 1);
 	info = &sig_info[sig];
@@ -45,14 +50,17 @@
 	r->is_user = save_user;
 }
 
-void user_signal(int sig, union uml_pt_regs *regs)
+extern int ptrace_faultinfo;
+
+void user_signal(int sig, union uml_pt_regs *regs, int pid)
 {
 	struct signal_info *info;
+        int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
+                    (sig == SIGILL) || (sig == SIGTRAP));
 
 	regs->skas.is_user = 1;
-	regs->skas.fault_addr = 0;
-	regs->skas.fault_type = 0;
-	regs->skas.trap_type = 0;
+	if (segv)
+		get_skas_faultinfo(pid, &regs->skas.faultinfo);
 	info = &sig_info[sig];
 	(*info->handler)(sig, regs);
 
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 7575ec4..7519528 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/compiler.h"
 #include "linux/stddef.h"
 #include "linux/kernel.h"
 #include "linux/string.h"
@@ -28,9 +29,12 @@
 	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
 		err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
 		if(err)
-			return(0);
+			return(-1UL);
 		phys = um_virt_to_phys(current, virt, NULL);
 	}
+        if(IS_ERR(phys))
+                phys = (void *) -1;
+
 	return((unsigned long) phys);
 }
 
@@ -41,7 +45,7 @@
 	int n;
 
 	addr = maybe_map(addr, is_write);
-	if(addr == -1)
+	if(addr == -1UL)
 		return(-1);
 
 	page = phys_to_page(addr);
@@ -61,8 +65,7 @@
 	void *arg;
 	int *res;
 
-	/* Some old gccs recognize __va_copy, but not va_copy */
-	__va_copy(args, *(va_list *)arg_ptr);
+	va_copy(args, *(va_list *)arg_ptr);
 	addr = va_arg(args, unsigned long);
 	len = va_arg(args, int);
 	is_write = va_arg(args, int);
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
index 17f5909..f7b7eba 100644
--- a/arch/um/kernel/skas/util/Makefile
+++ b/arch/um/kernel/skas/util/Makefile
@@ -2,3 +2,4 @@
 always			:= $(hostprogs-y)
 
 mk_ptregs-objs := mk_ptregs-$(SUBARCH).o
+HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um
diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c
index 0788dd0..1f96e1e 100644
--- a/arch/um/kernel/skas/util/mk_ptregs-i386.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c
@@ -1,8 +1,7 @@
 #include <stdio.h>
-#include <asm/ptrace.h>
-#include <asm/user.h>
+#include <user-offsets.h>
 
-#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val))
+#define SHOW(name) printf("#define %s %d\n", #name, name)
 
 int main(int argc, char **argv)
 {
@@ -12,28 +11,27 @@
 	printf("#ifndef __SKAS_PT_REGS_\n");
 	printf("#define __SKAS_PT_REGS_\n");
 	printf("\n");
-	printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE);
-	printf("#define HOST_FP_SIZE %d\n",
-	       sizeof(struct user_i387_struct) / sizeof(unsigned long));
-	printf("#define HOST_XFP_SIZE %d\n",
-	       sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
+	SHOW(HOST_FRAME_SIZE);
+	SHOW(HOST_FP_SIZE);
+	SHOW(HOST_XFP_SIZE);
 
-	PRINT_REG("IP", EIP);
-	PRINT_REG("SP", UESP);
-	PRINT_REG("EFLAGS", EFL);
-	PRINT_REG("EAX", EAX);
-	PRINT_REG("EBX", EBX);
-	PRINT_REG("ECX", ECX);
-	PRINT_REG("EDX", EDX);
-	PRINT_REG("ESI", ESI);
-	PRINT_REG("EDI", EDI);
-	PRINT_REG("EBP", EBP);
-	PRINT_REG("CS", CS);
-	PRINT_REG("SS", SS);
-	PRINT_REG("DS", DS);
-	PRINT_REG("FS", FS);
-	PRINT_REG("ES", ES);
-	PRINT_REG("GS", GS);
+	SHOW(HOST_IP);
+	SHOW(HOST_SP);
+	SHOW(HOST_EFLAGS);
+	SHOW(HOST_EAX);
+	SHOW(HOST_EBX);
+	SHOW(HOST_ECX);
+	SHOW(HOST_EDX);
+	SHOW(HOST_ESI);
+	SHOW(HOST_EDI);
+	SHOW(HOST_EBP);
+	SHOW(HOST_CS);
+	SHOW(HOST_SS);
+	SHOW(HOST_DS);
+	SHOW(HOST_FS);
+	SHOW(HOST_ES);
+	SHOW(HOST_GS);
+
 	printf("\n");
 	printf("#endif\n");
 	return(0);
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
index 67aee92..5fccbfe 100644
--- a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
+++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
@@ -5,11 +5,10 @@
  */
 
 #include <stdio.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
+#include <user-offsets.h>
 
-#define PRINT_REG(name, val) \
-	printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val))
+#define SHOW(name) \
+	printf("#define %s (%d / sizeof(unsigned long))\n", #name, name)
 
 int main(int argc, char **argv)
 {
@@ -18,36 +17,35 @@
 	printf("\n");
 	printf("#ifndef __SKAS_PT_REGS_\n");
 	printf("#define __SKAS_PT_REGS_\n");
-	printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n",
-	       FRAME_SIZE);
-	PRINT_REG("RBX", RBX);
-	PRINT_REG("RCX", RCX);
-	PRINT_REG("RDI", RDI);
-	PRINT_REG("RSI", RSI);
-	PRINT_REG("RDX", RDX);
-	PRINT_REG("RBP", RBP);
-	PRINT_REG("RAX", RAX);
-	PRINT_REG("R8", R8);
-	PRINT_REG("R9", R9);
-	PRINT_REG("R10", R10);
-	PRINT_REG("R11", R11);
-	PRINT_REG("R12", R12);
-	PRINT_REG("R13", R13);
-	PRINT_REG("R14", R14);
-	PRINT_REG("R15", R15);
-	PRINT_REG("ORIG_RAX", ORIG_RAX);
-	PRINT_REG("CS", CS);
-	PRINT_REG("SS", SS);
-	PRINT_REG("EFLAGS", EFLAGS);
+	SHOW(HOST_FRAME_SIZE);
+	SHOW(HOST_RBX);
+	SHOW(HOST_RCX);
+	SHOW(HOST_RDI);
+	SHOW(HOST_RSI);
+	SHOW(HOST_RDX);
+	SHOW(HOST_RBP);
+	SHOW(HOST_RAX);
+	SHOW(HOST_R8);
+	SHOW(HOST_R9);
+	SHOW(HOST_R10);
+	SHOW(HOST_R11);
+	SHOW(HOST_R12);
+	SHOW(HOST_R13);
+	SHOW(HOST_R14);
+	SHOW(HOST_R15);
+	SHOW(HOST_ORIG_RAX);
+	SHOW(HOST_CS);
+	SHOW(HOST_SS);
+	SHOW(HOST_EFLAGS);
 #if 0
-	PRINT_REG("FS", FS);
-	PRINT_REG("GS", GS);
-	PRINT_REG("DS", DS);
-	PRINT_REG("ES", ES);
+	SHOW(HOST_FS);
+	SHOW(HOST_GS);
+	SHOW(HOST_DS);
+	SHOW(HOST_ES);
 #endif
 
-	PRINT_REG("IP", RIP);
-	PRINT_REG("SP", RSP);
+	SHOW(HOST_IP);
+	SHOW(HOST_SP);
 	printf("#define HOST_FP_SIZE 0\n");
 	printf("#define HOST_XFP_SIZE 0\n");
 	printf("\n");
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
deleted file mode 100644
index 7fc06c8..0000000
--- a/arch/um/kernel/sys_call_table.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#include "linux/config.h"
-#include "linux/unistd.h"
-#include "linux/sys.h"
-#include "linux/swap.h"
-#include "linux/syscalls.h"
-#include "linux/sysctl.h"
-#include "asm/signal.h"
-#include "sysdep/syscalls.h"
-#include "kern_util.h"
-
-#ifdef CONFIG_NFSD
-#define NFSSERVCTL sys_nfsservctl
-#else
-#define NFSSERVCTL sys_ni_syscall
-#endif
-
-#define LAST_GENERIC_SYSCALL __NR_keyctl
-
-#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
-#define LAST_SYSCALL LAST_GENERIC_SYSCALL
-#else
-#define LAST_SYSCALL LAST_ARCH_SYSCALL
-#endif
-
-extern syscall_handler_t sys_fork;
-extern syscall_handler_t sys_execve;
-extern syscall_handler_t um_time;
-extern syscall_handler_t um_stime;
-extern syscall_handler_t sys_pipe;
-extern syscall_handler_t sys_olduname;
-extern syscall_handler_t sys_sigaction;
-extern syscall_handler_t sys_sigsuspend;
-extern syscall_handler_t old_readdir;
-extern syscall_handler_t sys_uname;
-extern syscall_handler_t sys_ipc;
-extern syscall_handler_t sys_sigreturn;
-extern syscall_handler_t sys_clone;
-extern syscall_handler_t sys_rt_sigreturn;
-extern syscall_handler_t sys_sigaltstack;
-extern syscall_handler_t sys_vfork;
-extern syscall_handler_t old_select;
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_mbind;
-extern syscall_handler_t sys_get_mempolicy;
-extern syscall_handler_t sys_set_mempolicy;
-extern syscall_handler_t sys_sys_setaltroot;
-
-syscall_handler_t *sys_call_table[] = {
-	[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
-	[ __NR_exit ] = (syscall_handler_t *) sys_exit,
-	[ __NR_fork ] = (syscall_handler_t *) sys_fork,
-	[ __NR_read ] = (syscall_handler_t *) sys_read,
-	[ __NR_write ] = (syscall_handler_t *) sys_write,
-
-	/* These three are declared differently in asm/unistd.h */
-	[ __NR_open ] = (syscall_handler_t *) sys_open,
-	[ __NR_close ] = (syscall_handler_t *) sys_close,
-	[ __NR_creat ] = (syscall_handler_t *) sys_creat,
-	[ __NR_link ] = (syscall_handler_t *) sys_link,
-	[ __NR_unlink ] = (syscall_handler_t *) sys_unlink,
-	[ __NR_execve ] = (syscall_handler_t *) sys_execve,
-
-	/* declared differently in kern_util.h */
-	[ __NR_chdir ] = (syscall_handler_t *) sys_chdir,
-	[ __NR_time ] = um_time,
-	[ __NR_mknod ] = (syscall_handler_t *) sys_mknod,
-	[ __NR_chmod ] = (syscall_handler_t *) sys_chmod,
-	[ __NR_lchown ] = (syscall_handler_t *) sys_lchown16,
-	[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
-	[ __NR_getpid ] = (syscall_handler_t *) sys_getpid,
-	[ __NR_mount ] = (syscall_handler_t *) sys_mount,
-	[ __NR_setuid ] = (syscall_handler_t *) sys_setuid16,
-	[ __NR_getuid ] = (syscall_handler_t *) sys_getuid16,
- 	[ __NR_ptrace ] = (syscall_handler_t *) sys_ptrace,
-	[ __NR_alarm ] = (syscall_handler_t *) sys_alarm,
-	[ __NR_pause ] = (syscall_handler_t *) sys_pause,
-	[ __NR_utime ] = (syscall_handler_t *) sys_utime,
-	[ __NR_access ] = (syscall_handler_t *) sys_access,
-	[ __NR_sync ] = (syscall_handler_t *) sys_sync,
-	[ __NR_kill ] = (syscall_handler_t *) sys_kill,
-	[ __NR_rename ] = (syscall_handler_t *) sys_rename,
-	[ __NR_mkdir ] = (syscall_handler_t *) sys_mkdir,
-	[ __NR_rmdir ] = (syscall_handler_t *) sys_rmdir,
-
-	/* Declared differently in asm/unistd.h */
-	[ __NR_dup ] = (syscall_handler_t *) sys_dup,
-	[ __NR_pipe ] = (syscall_handler_t *) sys_pipe,
-	[ __NR_times ] = (syscall_handler_t *) sys_times,
-	[ __NR_brk ] = (syscall_handler_t *) sys_brk,
-	[ __NR_setgid ] = (syscall_handler_t *) sys_setgid16,
-	[ __NR_getgid ] = (syscall_handler_t *) sys_getgid16,
-	[ __NR_geteuid ] = (syscall_handler_t *) sys_geteuid16,
-	[ __NR_getegid ] = (syscall_handler_t *) sys_getegid16,
-	[ __NR_acct ] = (syscall_handler_t *) sys_acct,
-	[ __NR_umount2 ] = (syscall_handler_t *) sys_umount,
-	[ __NR_ioctl ] = (syscall_handler_t *) sys_ioctl,
-	[ __NR_fcntl ] = (syscall_handler_t *) sys_fcntl,
-	[ __NR_setpgid ] = (syscall_handler_t *) sys_setpgid,
-	[ __NR_umask ] = (syscall_handler_t *) sys_umask,
-	[ __NR_chroot ] = (syscall_handler_t *) sys_chroot,
-	[ __NR_ustat ] = (syscall_handler_t *) sys_ustat,
-	[ __NR_dup2 ] = (syscall_handler_t *) sys_dup2,
-	[ __NR_getppid ] = (syscall_handler_t *) sys_getppid,
-	[ __NR_getpgrp ] = (syscall_handler_t *) sys_getpgrp,
-	[ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
-	[ __NR_setreuid ] = (syscall_handler_t *) sys_setreuid16,
-	[ __NR_setregid ] = (syscall_handler_t *) sys_setregid16,
-	[ __NR_sethostname ] = (syscall_handler_t *) sys_sethostname,
-	[ __NR_setrlimit ] = (syscall_handler_t *) sys_setrlimit,
-	[ __NR_getrlimit ] = (syscall_handler_t *) sys_old_getrlimit,
-	[ __NR_getrusage ] = (syscall_handler_t *) sys_getrusage,
-	[ __NR_gettimeofday ] = (syscall_handler_t *) sys_gettimeofday,
-	[ __NR_settimeofday ] = (syscall_handler_t *) sys_settimeofday,
-	[ __NR_getgroups ] = (syscall_handler_t *) sys_getgroups16,
-	[ __NR_setgroups ] = (syscall_handler_t *) sys_setgroups16,
-	[ __NR_symlink ] = (syscall_handler_t *) sys_symlink,
-	[ __NR_readlink ] = (syscall_handler_t *) sys_readlink,
-	[ __NR_uselib ] = (syscall_handler_t *) sys_uselib,
-	[ __NR_swapon ] = (syscall_handler_t *) sys_swapon,
-	[ __NR_reboot ] = (syscall_handler_t *) sys_reboot,
-	[ __NR_munmap ] = (syscall_handler_t *) sys_munmap,
-	[ __NR_truncate ] = (syscall_handler_t *) sys_truncate,
-	[ __NR_ftruncate ] = (syscall_handler_t *) sys_ftruncate,
-	[ __NR_fchmod ] = (syscall_handler_t *) sys_fchmod,
-	[ __NR_fchown ] = (syscall_handler_t *) sys_fchown16,
-	[ __NR_getpriority ] = (syscall_handler_t *) sys_getpriority,
-	[ __NR_setpriority ] = (syscall_handler_t *) sys_setpriority,
-	[ __NR_statfs ] = (syscall_handler_t *) sys_statfs,
-	[ __NR_fstatfs ] = (syscall_handler_t *) sys_fstatfs,
-	[ __NR_ioperm ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_syslog ] = (syscall_handler_t *) sys_syslog,
-	[ __NR_setitimer ] = (syscall_handler_t *) sys_setitimer,
-	[ __NR_getitimer ] = (syscall_handler_t *) sys_getitimer,
-	[ __NR_stat ] = (syscall_handler_t *) sys_newstat,
-	[ __NR_lstat ] = (syscall_handler_t *) sys_newlstat,
-	[ __NR_fstat ] = (syscall_handler_t *) sys_newfstat,
-	[ __NR_vhangup ] = (syscall_handler_t *) sys_vhangup,
-	[ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
-	[ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff,
-	[ __NR_sysinfo ] = (syscall_handler_t *) sys_sysinfo,
-	[ __NR_fsync ] = (syscall_handler_t *) sys_fsync,
-	[ __NR_clone ] = (syscall_handler_t *) sys_clone,
-	[ __NR_setdomainname ] = (syscall_handler_t *) sys_setdomainname,
-	[ __NR_uname ] = (syscall_handler_t *) sys_newuname,
-	[ __NR_adjtimex ] = (syscall_handler_t *) sys_adjtimex,
-	[ __NR_mprotect ] = (syscall_handler_t *) sys_mprotect,
-	[ __NR_create_module ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_init_module ] = (syscall_handler_t *) sys_init_module,
-	[ __NR_delete_module ] = (syscall_handler_t *) sys_delete_module,
-	[ __NR_get_kernel_syms ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_quotactl ] = (syscall_handler_t *) sys_quotactl,
-	[ __NR_getpgid ] = (syscall_handler_t *) sys_getpgid,
-	[ __NR_fchdir ] = (syscall_handler_t *) sys_fchdir,
-	[ __NR_sysfs ] = (syscall_handler_t *) sys_sysfs,
-	[ __NR_personality ] = (syscall_handler_t *) sys_personality,
-	[ __NR_afs_syscall ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_setfsuid ] = (syscall_handler_t *) sys_setfsuid16,
-	[ __NR_setfsgid ] = (syscall_handler_t *) sys_setfsgid16,
-	[ __NR_getdents ] = (syscall_handler_t *) sys_getdents,
-	[ __NR_flock ] = (syscall_handler_t *) sys_flock,
-	[ __NR_msync ] = (syscall_handler_t *) sys_msync,
-	[ __NR_readv ] = (syscall_handler_t *) sys_readv,
-	[ __NR_writev ] = (syscall_handler_t *) sys_writev,
-	[ __NR_getsid ] = (syscall_handler_t *) sys_getsid,
-	[ __NR_fdatasync ] = (syscall_handler_t *) sys_fdatasync,
-	[ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl,
-	[ __NR_mlock ] = (syscall_handler_t *) sys_mlock,
-	[ __NR_munlock ] = (syscall_handler_t *) sys_munlock,
-	[ __NR_mlockall ] = (syscall_handler_t *) sys_mlockall,
-	[ __NR_munlockall ] = (syscall_handler_t *) sys_munlockall,
-	[ __NR_sched_setparam ] = (syscall_handler_t *) sys_sched_setparam,
-	[ __NR_sched_getparam ] = (syscall_handler_t *) sys_sched_getparam,
-	[ __NR_sched_setscheduler ] = (syscall_handler_t *) sys_sched_setscheduler,
-	[ __NR_sched_getscheduler ] = (syscall_handler_t *) sys_sched_getscheduler,
-	[ __NR_sched_yield ] = (syscall_handler_t *) yield,
-	[ __NR_sched_get_priority_max ] = (syscall_handler_t *) sys_sched_get_priority_max,
-	[ __NR_sched_get_priority_min ] = (syscall_handler_t *) sys_sched_get_priority_min,
-	[ __NR_sched_rr_get_interval ] = (syscall_handler_t *) sys_sched_rr_get_interval,
-	[ __NR_nanosleep ] = (syscall_handler_t *) sys_nanosleep,
-	[ __NR_mremap ] = (syscall_handler_t *) sys_mremap,
-	[ __NR_setresuid ] = (syscall_handler_t *) sys_setresuid16,
-	[ __NR_getresuid ] = (syscall_handler_t *) sys_getresuid16,
-	[ __NR_query_module ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_poll ] = (syscall_handler_t *) sys_poll,
-	[ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL,
-	[ __NR_setresgid ] = (syscall_handler_t *) sys_setresgid16,
-	[ __NR_getresgid ] = (syscall_handler_t *) sys_getresgid16,
-	[ __NR_prctl ] = (syscall_handler_t *) sys_prctl,
-	[ __NR_rt_sigreturn ] = (syscall_handler_t *) sys_rt_sigreturn,
-	[ __NR_rt_sigaction ] = (syscall_handler_t *) sys_rt_sigaction,
-	[ __NR_rt_sigprocmask ] = (syscall_handler_t *) sys_rt_sigprocmask,
-	[ __NR_rt_sigpending ] = (syscall_handler_t *) sys_rt_sigpending,
-	[ __NR_rt_sigtimedwait ] = (syscall_handler_t *) sys_rt_sigtimedwait,
-	[ __NR_rt_sigqueueinfo ] = (syscall_handler_t *) sys_rt_sigqueueinfo,
-	[ __NR_rt_sigsuspend ] = (syscall_handler_t *) sys_rt_sigsuspend,
-	[ __NR_pread64 ] = (syscall_handler_t *) sys_pread64,
-	[ __NR_pwrite64 ] = (syscall_handler_t *) sys_pwrite64,
-	[ __NR_chown ] = (syscall_handler_t *) sys_chown16,
-	[ __NR_getcwd ] = (syscall_handler_t *) sys_getcwd,
-	[ __NR_capget ] = (syscall_handler_t *) sys_capget,
-	[ __NR_capset ] = (syscall_handler_t *) sys_capset,
-	[ __NR_sigaltstack ] = (syscall_handler_t *) sys_sigaltstack,
-	[ __NR_sendfile ] = (syscall_handler_t *) sys_sendfile,
-	[ __NR_getpmsg ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_putpmsg ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_vfork ] = (syscall_handler_t *) sys_vfork,
-	[ __NR_getdents64 ] = (syscall_handler_t *) sys_getdents64,
-	[ __NR_gettid ] = (syscall_handler_t *) sys_gettid,
-	[ __NR_readahead ] = (syscall_handler_t *) sys_readahead,
-	[ __NR_setxattr ] = (syscall_handler_t *) sys_setxattr,
-	[ __NR_lsetxattr ] = (syscall_handler_t *) sys_lsetxattr,
-	[ __NR_fsetxattr ] = (syscall_handler_t *) sys_fsetxattr,
-	[ __NR_getxattr ] = (syscall_handler_t *) sys_getxattr,
-	[ __NR_lgetxattr ] = (syscall_handler_t *) sys_lgetxattr,
-	[ __NR_fgetxattr ] = (syscall_handler_t *) sys_fgetxattr,
-	[ __NR_listxattr ] = (syscall_handler_t *) sys_listxattr,
-	[ __NR_llistxattr ] = (syscall_handler_t *) sys_llistxattr,
-	[ __NR_flistxattr ] = (syscall_handler_t *) sys_flistxattr,
-	[ __NR_removexattr ] = (syscall_handler_t *) sys_removexattr,
-	[ __NR_lremovexattr ] = (syscall_handler_t *) sys_lremovexattr,
-	[ __NR_fremovexattr ] = (syscall_handler_t *) sys_fremovexattr,
-	[ __NR_tkill ] = (syscall_handler_t *) sys_tkill,
-	[ __NR_futex ] = (syscall_handler_t *) sys_futex,
-	[ __NR_sched_setaffinity ] = (syscall_handler_t *) sys_sched_setaffinity,
-	[ __NR_sched_getaffinity ] = (syscall_handler_t *) sys_sched_getaffinity,
-	[ __NR_io_setup ] = (syscall_handler_t *) sys_io_setup,
-	[ __NR_io_destroy ] = (syscall_handler_t *) sys_io_destroy,
-	[ __NR_io_getevents ] = (syscall_handler_t *) sys_io_getevents,
-	[ __NR_io_submit ] = (syscall_handler_t *) sys_io_submit,
-	[ __NR_io_cancel ] = (syscall_handler_t *) sys_io_cancel,
-	[ __NR_exit_group ] = (syscall_handler_t *) sys_exit_group,
-	[ __NR_lookup_dcookie ] = (syscall_handler_t *) sys_lookup_dcookie,
-	[ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create,
-	[ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl,
-	[ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait,
-	[ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages,
-	[ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
-	[ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create,
-	[ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime,
-	[ __NR_timer_gettime ] = (syscall_handler_t *) sys_timer_gettime,
-	[ __NR_timer_getoverrun ] = (syscall_handler_t *) sys_timer_getoverrun,
-	[ __NR_timer_delete ] = (syscall_handler_t *) sys_timer_delete,
-	[ __NR_clock_settime ] = (syscall_handler_t *) sys_clock_settime,
-	[ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime,
-	[ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres,
-	[ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep,
-	[ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill,
-	[ __NR_utimes ] = (syscall_handler_t *) sys_utimes,
-	[ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64,
-	[ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_mbind ] = (syscall_handler_t *) sys_mbind,
-	[ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy,
-	[ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy,
-	[ __NR_mq_open ] = (syscall_handler_t *) sys_mq_open,
-	[ __NR_mq_unlink ] = (syscall_handler_t *) sys_mq_unlink,
-	[ __NR_mq_timedsend ] = (syscall_handler_t *) sys_mq_timedsend,
-	[ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive,
-	[ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify,
-	[ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr,
-	[ __NR_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
-	[ __NR_waitid ] = (syscall_handler_t *) sys_waitid,
-	[ __NR_add_key ] = (syscall_handler_t *) sys_add_key,
-	[ __NR_request_key ] = (syscall_handler_t *) sys_request_key,
-	[ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl,
-
-	ARCH_SYSCALLS
-	[ LAST_SYSCALL + 1 ... NR_syscalls ] = 
-		(syscall_handler_t *) sys_ni_syscall
-};
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 42731e0..b7a5525 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -17,7 +17,6 @@
 #include "linux/utime.h"
 #include "asm/mman.h"
 #include "asm/uaccess.h"
-#include "asm/ipc.h"
 #include "kern_util.h"
 #include "user_util.h"
 #include "sysdep/syscalls.h"
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 2461cd7..6516fc5 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -48,8 +48,6 @@
 static long long delta;   		/* Deviation per interval */
 #endif
 
-#define MILLION 1000000
-
 void timer_irq(union uml_pt_regs *regs)
 {
 	unsigned long long ticks = 0;
@@ -136,22 +134,6 @@
 	return 0;
 }
 
-void __udelay(unsigned long usecs)
-{
-	int i, n;
-
-	n = (loops_per_jiffy * HZ * usecs) / MILLION;
-	for(i=0;i<n;i++) ;
-}
-
-void __const_udelay(unsigned long usecs)
-{
-	int i, n;
-
-	n = (loops_per_jiffy * HZ * usecs) / MILLION;
-	for(i=0;i<n;i++) ;
-}
-
 void timer_handler(int sig, union uml_pt_regs *regs)
 {
 	local_irq_disable();
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 47e766e..5fca2c6 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -48,7 +48,7 @@
 		goto good_area;
 	else if(!(vma->vm_flags & VM_GROWSDOWN)) 
 		goto out;
-	else if(!ARCH_IS_STACKGROW(address))
+	else if(is_user && !ARCH_IS_STACKGROW(address))
 		goto out;
 	else if(expand_stack(vma, address)) 
 		goto out;
@@ -133,12 +133,19 @@
 	return(0);
 }
 
-unsigned long segv(unsigned long address, unsigned long ip, int is_write, 
-		   int is_user, void *sc)
+/*
+ * We give a *copy* of the faultinfo in the regs to segv.
+ * This must be done, since nesting SEGVs could overwrite
+ * the info in the regs. A pointer to the info then would
+ * give us bad data!
+ */
+unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
 {
 	struct siginfo si;
 	void *catcher;
 	int err;
+        int is_write = FAULT_WRITE(fi);
+        unsigned long address = FAULT_ADDRESS(fi);
 
         if(!is_user && (address >= start_vm) && (address < end_vm)){
                 flush_tlb_kernel_vm();
@@ -159,7 +166,7 @@
 	} 
 	else if(current->thread.fault_addr != NULL)
 		panic("fault_addr set but no fault catcher");
-	else if(arch_fixup(ip, sc))
+        else if(!is_user && arch_fixup(ip, sc))
 		return(0);
 
  	if(!is_user) 
@@ -171,6 +178,7 @@
 		si.si_errno = 0;
 		si.si_code = BUS_ADRERR;
 		si.si_addr = (void *)address;
+                current->thread.arch.faultinfo = fi;
 		force_sig_info(SIGBUS, &si, current);
 	}
 	else if(err == -ENOMEM){
@@ -180,22 +188,20 @@
 	else {
 		si.si_signo = SIGSEGV;
 		si.si_addr = (void *) address;
-		current->thread.cr2 = address;
-		current->thread.err = is_write;
+                current->thread.arch.faultinfo = fi;
 		force_sig_info(SIGSEGV, &si, current);
 	}
 	return(0);
 }
 
-void bad_segv(unsigned long address, unsigned long ip, int is_write)
+void bad_segv(struct faultinfo fi, unsigned long ip)
 {
 	struct siginfo si;
 
 	si.si_signo = SIGSEGV;
 	si.si_code = SEGV_ACCERR;
-	si.si_addr = (void *) address;
-	current->thread.cr2 = address;
-	current->thread.err = is_write;
+        si.si_addr = (void *) FAULT_ADDRESS(fi);
+        current->thread.arch.faultinfo = fi;
 	force_sig_info(SIGSEGV, &si, current);
 }
 
@@ -204,6 +210,7 @@
 	if(arch_handle_signal(sig, regs)) return;
 	if(!UPT_IS_USER(regs))
 		panic("Kernel mode signal %d", sig);
+        current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
 	force_sig(sig, current);
 }
 
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 50a4042..f825a6e 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -54,23 +54,22 @@
 void segv_handler(int sig, union uml_pt_regs *regs)
 {
 	int index, max;
+        struct faultinfo * fi = UPT_FAULTINFO(regs);
 
-	if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){
-		bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), 
-			 UPT_FAULT_WRITE(regs));
+        if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
+                bad_segv(*fi, UPT_IP(regs));
 		return;
 	}
 	max = sizeof(segfault_record)/sizeof(segfault_record[0]);
 	index = next_trap_index(max);
 
 	nsegfaults++;
-	segfault_record[index].address = UPT_FAULT_ADDR(regs);
+        segfault_record[index].address = FAULT_ADDRESS(*fi);
 	segfault_record[index].pid = os_getpid();
-	segfault_record[index].is_write = UPT_FAULT_WRITE(regs);
+        segfault_record[index].is_write = FAULT_WRITE(*fi);
 	segfault_record[index].sp = UPT_SP(regs);
 	segfault_record[index].is_user = UPT_IS_USER(regs);
-	segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs),
-	     UPT_IS_USER(regs), regs);
+        segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
 }
 
 void usr2_handler(int sig, union uml_pt_regs *regs)
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index 3d5177d..c3faea2 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -4,6 +4,7 @@
 #
 
 extra-y := unmap_fin.o
+targets := unmap.o
 clean-files := unmap_tmp.o
 
 obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
index 28aaab3..e0ca0e0 100644
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ b/arch/um/kernel/tt/include/mode_kern-tt.h
@@ -19,7 +19,6 @@
 			  unsigned long stack_top, struct task_struct *p,
 			  struct pt_regs *regs);
 extern void release_thread_tt(struct task_struct *task);
-extern void exit_thread_tt(void);
 extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
 extern void init_idle_tt(void);
 extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h
index f0bad01..3fbb5fe 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/kernel/tt/include/uaccess-tt.h
@@ -34,7 +34,7 @@
           (under_task_size(addr, size) || is_stack(addr, size))))
 
 static inline int verify_area_tt(int type, const void * addr,
-				 unsigned long size)
+                                 unsigned long size)
 {
 	return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
 }
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 74346a0..bcb8796 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -21,14 +21,8 @@
 	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
 }
 
-#ifdef CONFIG_HOST_2G_2G
-#define TOP 0x80000000
-#else
-#define TOP 0xc0000000
-#endif
-
 #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
-#define START (TOP - SIZE)
+#define START (CONFIG_TOP_ADDR - SIZE)
 
 unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, 
 				unsigned long *task_size_out)
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index f19f7c1..df810ca 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -65,8 +65,7 @@
 		panic("write of switch_pipe failed, err = %d", -err);
 
 	reading = 1;
-	if((from->exit_state == EXIT_ZOMBIE) ||
-	   (from->exit_state == EXIT_DEAD))
+        if(from->thread.mode.tt.switch_pipe[0] == -1)
 		os_kill_process(os_getpid(), 0);
 
 	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
@@ -81,8 +80,7 @@
 	 * in case it has not already killed itself.
 	 */
 	prev_sched = current->thread.prev_sched;
-	if((prev_sched->exit_state == EXIT_ZOMBIE) ||
-	   (prev_sched->exit_state == EXIT_DEAD))
+        if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
 		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
 
 	change_sig(SIGVTALRM, vtalrm);
@@ -101,14 +99,18 @@
 {
 	int pid = task->thread.mode.tt.extern_pid;
 
+	/*
+         * We first have to kill the other process, before
+         * closing its switch_pipe. Else it might wake up
+         * and receive "EOF" before we could kill it.
+         */
 	if(os_getpid() != pid)
 		os_kill_process(pid, 0);
-}
 
-void exit_thread_tt(void)
-{
-	os_close_file(current->thread.mode.tt.switch_pipe[0]);
-	os_close_file(current->thread.mode.tt.switch_pipe[1]);
+        os_close_file(task->thread.mode.tt.switch_pipe[0]);
+        os_close_file(task->thread.mode.tt.switch_pipe[1]);
+	/* use switch_pipe as flag: thread is released */
+        task->thread.mode.tt.switch_pipe[0] = -1;
 }
 
 void suspend_new_thread(int fd)
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index e4e7e9c..b218316 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -63,6 +63,10 @@
 
 	UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
 
+#ifdef UPT_ORIGGPR2
+        UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs);
+#endif
+
 	if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
 	   ((unsigned long *) PT_IP(proc_regs) <= &_etext))
 		tracer_panic("I'm tracing myself and I can't get out");
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index 7b5d937..d11e739 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -26,6 +26,7 @@
 #include "kern_util.h"
 #include "chan_user.h"
 #include "ptrace_user.h"
+#include "irq_user.h"
 #include "mode.h"
 #include "tt.h"
 
@@ -33,7 +34,7 @@
 
 int is_tracer_winch(int pid, int fd, void *data)
 {
-	if(pid != tracing_pid)
+	if(pid != os_getpgrp())
 		return(0);
 
 	register_winch_irq(tracer_winch[0], fd, -1, data);
@@ -89,8 +90,10 @@
 
 static void tracer_segv(int sig, struct sigcontext sc)
 {
+        struct faultinfo fi;
+        GET_FAULTINFO_FROM_SC(fi, &sc);
 	printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
-	       SC_FAULT_ADDR(&sc), SC_IP(&sc));
+               FAULT_ADDRESS(fi), SC_IP(&sc));
 	while(1)
 		pause();
 }
@@ -117,6 +120,7 @@
 	signal(SIGSEGV, (__sighandler_t) sig_handler);
 	set_cmdline("(idle thread)");
 	set_init_pid(os_getpid());
+	init_irq_signals(0);
 	proc = arg;
 	return((*proc)(NULL));
 }
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index 92a3820..fc10861 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -7,6 +7,7 @@
 #include <errno.h>
 #include <signal.h>
 #include "sysdep/ptrace.h"
+#include "sysdep/sigcontext.h"
 #include "signal_user.h"
 #include "user_util.h"
 #include "kern_util.h"
@@ -28,6 +29,11 @@
 		change_sig(SIGSEGV, 1);
 
 	r = &TASK_REGS(get_current())->tt;
+        if ( sig == SIGFPE || sig == SIGSEGV ||
+             sig == SIGBUS || sig == SIGILL ||
+             sig == SIGTRAP ) {
+                GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
+        }
 	save_regs = *r;
 	is_user = user_context(SC_SP(sc));
 	r->sc = sc;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 5c49d88..4d10ec3 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -23,6 +23,7 @@
 #include "asm/ptrace.h"
 #include "asm/elf.h"
 #include "asm/user.h"
+#include "asm/setup.h"
 #include "ubd_user.h"
 #include "asm/current.h"
 #include "asm/setup.h"
@@ -42,9 +43,9 @@
 #define DEFAULT_COMMAND_LINE "root=98:0"
 
 /* Changed in linux_main and setup_arch, which run before SMP is started */
-char command_line[COMMAND_LINE_SIZE] = { 0 };
+static char command_line[COMMAND_LINE_SIZE] = { 0 };
 
-void add_arg(char *arg)
+static void add_arg(char *arg)
 {
 	if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
 		printf("add_arg: Too many command line arguments!\n");
@@ -449,7 +450,7 @@
 {
 	notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
 	paging_init();
- 	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+        strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
  	*cmdline_p = command_line;
 	setup_hostinfo();
 }
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..1660a76
--- /dev/null
+++ b/arch/um/kernel/vmlinux.lds.S
@@ -0,0 +1,6 @@
+#include <linux/config.h>
+#ifdef CONFIG_LD_SCRIPT_STATIC
+#include "uml.lds.S"
+#else
+#include "dyn.lds.S"
+#endif
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index ba9ca1c..1e126bf 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -123,6 +123,11 @@
 	return(getpid());
 }
 
+int os_getpgrp(void)
+{
+	return getpgrp();
+}
+
 int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
 		  int r, int w, int x)
 {
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 7eac1ba..c7bfd5e 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -8,7 +8,7 @@
 #include "mode.h"
 #include "sysdep/signal.h"
 
-void sig_handler(int sig)
+void sig_handler(ARCH_SIGHDLR_PARAM)
 {
 	struct sigcontext *sc;
 
@@ -19,7 +19,7 @@
 
 extern int timer_irq_inited;
 
-void alarm_handler(int sig)
+void alarm_handler(ARCH_SIGHDLR_PARAM)
 {
 	struct sigcontext *sc;
 
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 148645b..9a0ad09 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -105,14 +105,15 @@
 		panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
 		      err);
 
+	errno = 0;
 	err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
 	if(!err)
 		return;
+	if(errno != EIO)
+		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+		      errno);
 
 	have_fpx_regs = 0;
-	if(err != EIO)
-		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
-		      err);
 
 	err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
 	if(err)
diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile
index fb00ddf..9778aed 100644
--- a/arch/um/os-Linux/util/Makefile
+++ b/arch/um/os-Linux/util/Makefile
@@ -1,4 +1,4 @@
 hostprogs-y		:= mk_user_constants
 always			:= $(hostprogs-y)
 
-mk_user_constants-objs	:= mk_user_constants.o
+HOSTCFLAGS_mk_user_constants.o := -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c
index 0933518..4838f30 100644
--- a/arch/um/os-Linux/util/mk_user_constants.c
+++ b/arch/um/os-Linux/util/mk_user_constants.c
@@ -1,11 +1,5 @@
 #include <stdio.h>
-#include <asm/types.h>
-/* For some reason, x86_64 nowhere defines u64 and u32, even though they're
- * used throughout the headers.
- */
-typedef __u64 u64;
-typedef __u32 u32;
-#include <asm/user.h>
+#include <user-offsets.h>
 
 int main(int argc, char **argv)
 {
@@ -20,7 +14,7 @@
    * x86_64 (216 vs 168 bytes).  user_regs_struct is the correct size on
    * both x86_64 and i386.
    */
-  printf("#define UM_FRAME_SIZE %d\n", (int) sizeof(struct user_regs_struct));
+  printf("#define UM_FRAME_SIZE %d\n", __UM_FRAME_SIZE);
 
   printf("\n");
   printf("#endif\n");
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 143f6fe..0b24918 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -2,12 +2,27 @@
 # arch/um: Generic definitions
 # ===========================================================================
 
-USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
-USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
-
+USER_SINGLE_OBJS := \
+	$(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
+USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m)  $(USER_SINGLE_OBJS))
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-$(USER_OBJS): c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
+$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
+	$(CFLAGS_$(notdir $@))
 
 quiet_cmd_make_link = SYMLINK $@
-cmd_make_link       = rm -f $@; ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
+cmd_make_link       = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
+
+# this needs to be before the foreach, because targets does not accept
+# complete paths like $(obj)/$(f). To make sure this works, use a := assignment,
+# or we will get $(obj)/$(f) in the "targets" value.
+# Also, this forces you to use the := syntax when assigning to targets.
+# Otherwise the line below will cause an infinite loop (if you don't know why,
+# just do it).
+
+targets := $(targets) $(SYMLINKS)
+
+SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$(f))
+
+$(SYMLINKS): FORCE
+	$(call if_changed,make_link)
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 71b47e6..fcd67c3 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,29 +1,19 @@
 obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
-	ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o
+	ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \
+	sys_call_table.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
 obj-$(CONFIG_MODULES) += module.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 
-include arch/um/scripts/Makefile.rules
-
 SYMLINKS = bitops.c semaphore.c highmem.c module.c
 
-# this needs to be before the foreach, because clean-files does not accept
-# complete paths like $(src)/$f.
-clean-files := $(SYMLINKS)
-
-targets += $(SYMLINKS)
-
-SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f)
-
 bitops.c-dir = lib
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
 
-$(SYMLINKS): FORCE
-	$(call if_changed,make_link)
-
 subdir- := util
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S
index a11171f..d98b2ff 100644
--- a/arch/um/sys-i386/checksum.S
+++ b/arch/um/sys-i386/checksum.S
@@ -38,7 +38,7 @@
 		
 .text
 .align 4
-.globl arch_csum_partial								
+.globl csum_partial
 		
 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
 
@@ -49,7 +49,7 @@
 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
 	   * alignment for the unrolled loop.
 	   */		
-arch_csum_partial:	
+csum_partial:
 	pushl %esi
 	pushl %ebx
 	movl 20(%esp),%eax	# Function arg: unsigned int sum
@@ -119,7 +119,7 @@
 
 /* Version for PentiumII/PPro */
 
-arch_csum_partial:
+csum_partial:
 	pushl %esi
 	pushl %ebx
 	movl 20(%esp),%eax	# Function arg: unsigned int sum
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index 20d37db..e9892ee 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,3 +1,6 @@
+#include "linux/delay.h"
+#include "asm/param.h"
+
 void __delay(unsigned long time)
 {
 	/* Stolen from the i386 __loop_delay */
@@ -12,3 +15,18 @@
 		:"0" (time));
 }
 
+void __udelay(unsigned long usecs)
+{
+	int i, n;
+
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
+	for(i=0;i<n;i++) ;
+}
+
+void __const_udelay(unsigned long usecs)
+{
+	int i, n;
+
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
+	for(i=0;i<n;i++) ;
+}
diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/sys-i386/kernel-offsets.c
new file mode 100644
index 0000000..9f8ecd1
--- /dev/null
+++ b/arch/um/sys-i386/kernel-offsets.c
@@ -0,0 +1,25 @@
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <asm/page.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define STR(x) #x
+#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+	OFFSET(TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+#ifdef CONFIG_MODE_TT
+	OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
+#endif
+#include <common-offsets.h>
+}
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
index 74f70a1..db524ab3 100644
--- a/arch/um/sys-i386/ksyms.c
+++ b/arch/um/sys-i386/ksyms.c
@@ -2,6 +2,7 @@
 #include "linux/in6.h"
 #include "linux/rwsem.h"
 #include "asm/byteorder.h"
+#include "asm/delay.h"
 #include "asm/semaphore.h"
 #include "asm/uaccess.h"
 #include "asm/checksum.h"
@@ -13,5 +14,8 @@
 EXPORT_SYMBOL(__up_wakeup);
 
 /* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_from);
-EXPORT_SYMBOL(csum_partial_copy_to);
+EXPORT_SYMBOL(csum_partial);
+
+/* delay core functions */
+EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 31bcb2f..dc755b0 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -25,7 +25,7 @@
 #endif
 
 #ifdef CONFIG_MODE_SKAS
-extern int userspace_pid;
+extern int userspace_pid[];
 
 #include "skas_ptrace.h"
 
@@ -56,7 +56,8 @@
 	ldt = ((struct ptrace_ldt) { .func	= func,
 				     .ptr	= buf,
 				     .bytecount = bytecount });
-	res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt);
+#warning Need to look up userspace_pid by cpu
+	res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
 	if(res < 0)
 		goto out;
 
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index e470d28..e839ce6 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -73,6 +73,25 @@
 	return 0;
 }
 
+int poke_user(struct task_struct *child, long addr, long data)
+{
+        if ((addr & 3) || addr < 0)
+                return -EIO;
+
+        if (addr < MAX_REG_OFFSET)
+                return putreg(child, addr, data);
+
+        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+                (addr <= offsetof(struct user, u_debugreg[7]))){
+                addr -= offsetof(struct user, u_debugreg[0]);
+                addr = addr >> 2;
+                if((addr == 4) || (addr == 5)) return -EIO;
+                child->thread.arch.debugregs[addr] = data;
+                return 0;
+        }
+        return -EIO;
+}
+
 unsigned long getreg(struct task_struct *child, int regno)
 {
 	unsigned long retval = ~0UL;
@@ -93,6 +112,27 @@
 	return retval;
 }
 
+int peek_user(struct task_struct *child, long addr, long data)
+{
+/* read the word at location addr in the USER area. */
+        unsigned long tmp;
+
+        if ((addr & 3) || addr < 0)
+                return -EIO;
+
+        tmp = 0;  /* Default return condition */
+        if(addr < MAX_REG_OFFSET){
+                tmp = getreg(child, addr);
+        }
+        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+                (addr <= offsetof(struct user, u_debugreg[7]))){
+                addr -= offsetof(struct user, u_debugreg[0]);
+                addr = addr >> 2;
+                tmp = child->thread.arch.debugregs[addr];
+        }
+        return put_user(tmp, (unsigned long *) data);
+}
+
 struct i387_fxsave_struct {
 	unsigned short	cwd;
 	unsigned short	swd;
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 76ba872..03913ca 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -47,9 +47,6 @@
 	REGS_CS(regs->regs.skas.regs) = sc.cs;
 	REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
 	REGS_SS(regs->regs.skas.regs) = sc.ss;
-	regs->regs.skas.fault_addr = sc.cr2;
-	regs->regs.skas.fault_type = FAULT_WRITE(sc.err);
-	regs->regs.skas.trap_type = sc.trapno;
 
 	err = restore_fp_registers(userspace_pid[0], fpregs);
 	if(err < 0){
@@ -62,11 +59,11 @@
 }
 
 int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
-			 struct pt_regs *regs, unsigned long fault_addr,
-			 int fault_type)
+                         struct pt_regs *regs)
 {
   	struct sigcontext sc;
 	unsigned long fpregs[HOST_FP_SIZE];
+	struct faultinfo * fi = &current->thread.arch.faultinfo;
 	int err;
 
 	sc.gs = REGS_GS(regs->regs.skas.regs);
@@ -86,9 +83,9 @@
 	sc.eflags = REGS_EFLAGS(regs->regs.skas.regs);
 	sc.esp_at_signal = regs->regs.skas.regs[UESP];
 	sc.ss = regs->regs.skas.regs[SS];
-	sc.cr2 = fault_addr;
-	sc.err = TO_SC_ERR(fault_type);
-	sc.trapno = regs->regs.skas.trap_type;
+        sc.cr2 = fi->cr2;
+        sc.err = fi->error_code;
+        sc.trapno = fi->trap_no;
 
 	err = save_fp_registers(userspace_pid[0], fpregs);
 	if(err < 0){
@@ -167,9 +164,7 @@
 {
 	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
 					      sizeof(*fp)),
-			   copy_sc_to_user_skas(to, fp, from,
-						current->thread.cr2,
-						current->thread.err)));
+                           copy_sc_to_user_skas(to, fp, from)));
 }
 
 static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp,
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
new file mode 100644
index 0000000..ad75c27
--- /dev/null
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -0,0 +1,16 @@
+#include <linux/linkage.h>
+/* Steal i386 syscall table for our purposes, but with some slight changes.*/
+
+#define sys_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+#define sys_vm86old sys_ni_syscall
+#define sys_vm86 sys_ni_syscall
+#define sys_set_thread_area sys_ni_syscall
+#define sys_get_thread_area sys_ni_syscall
+
+#define sys_stime um_stime
+#define sys_time um_time
+#define old_mmap old_mmap_i386
+
+#include "../../i386/kernel/syscall_table.S"
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
new file mode 100644
index 0000000..3ceaabc
--- /dev/null
+++ b/arch/um/sys-i386/user-offsets.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <signal.h>
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <linux/stddef.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+	OFFSET(SC_IP, sigcontext, eip);
+	OFFSET(SC_SP, sigcontext, esp);
+	OFFSET(SC_FS, sigcontext, fs);
+	OFFSET(SC_GS, sigcontext, gs);
+	OFFSET(SC_DS, sigcontext, ds);
+	OFFSET(SC_ES, sigcontext, es);
+	OFFSET(SC_SS, sigcontext, ss);
+	OFFSET(SC_CS, sigcontext, cs);
+	OFFSET(SC_EFLAGS, sigcontext, eflags);
+	OFFSET(SC_EAX, sigcontext, eax);
+	OFFSET(SC_EBX, sigcontext, ebx);
+	OFFSET(SC_ECX, sigcontext, ecx);
+	OFFSET(SC_EDX, sigcontext, edx);
+	OFFSET(SC_EDI, sigcontext, edi);
+	OFFSET(SC_ESI, sigcontext, esi);
+	OFFSET(SC_EBP, sigcontext, ebp);
+	OFFSET(SC_TRAPNO, sigcontext, trapno);
+	OFFSET(SC_ERR, sigcontext, err);
+	OFFSET(SC_CR2, sigcontext, cr2);
+	OFFSET(SC_FPSTATE, sigcontext, fpstate);
+	OFFSET(SC_SIGMASK, sigcontext, oldmask);
+	OFFSET(SC_FP_CW, _fpstate, cw);
+	OFFSET(SC_FP_SW, _fpstate, sw);
+	OFFSET(SC_FP_TAG, _fpstate, tag);
+	OFFSET(SC_FP_IPOFF, _fpstate, ipoff);
+	OFFSET(SC_FP_CSSEL, _fpstate, cssel);
+	OFFSET(SC_FP_DATAOFF, _fpstate, dataoff);
+	OFFSET(SC_FP_DATASEL, _fpstate, datasel);
+	OFFSET(SC_FP_ST, _fpstate, _st);
+	OFFSET(SC_FXSR_ENV, _fpstate, _fxsr_env);
+
+	DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
+	DEFINE(HOST_FP_SIZE,
+		sizeof(struct user_i387_struct) / sizeof(unsigned long));
+	DEFINE(HOST_XFP_SIZE,
+	       sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
+
+	DEFINE(HOST_IP, EIP);
+	DEFINE(HOST_SP, UESP);
+	DEFINE(HOST_EFLAGS, EFL);
+	DEFINE(HOST_EAX, EAX);
+	DEFINE(HOST_EBX, EBX);
+	DEFINE(HOST_ECX, ECX);
+	DEFINE(HOST_EDX, EDX);
+	DEFINE(HOST_ESI, ESI);
+	DEFINE(HOST_EDI, EDI);
+	DEFINE(HOST_EBP, EBP);
+	DEFINE(HOST_CS, CS);
+	DEFINE(HOST_SS, SS);
+	DEFINE(HOST_DS, DS);
+	DEFINE(HOST_FS, FS);
+	DEFINE(HOST_ES, ES);
+	DEFINE(HOST_GS, GS);
+	DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+}
diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
index 34860f9..bf61afd 100644
--- a/arch/um/sys-i386/util/Makefile
+++ b/arch/um/sys-i386/util/Makefile
@@ -1,8 +1,5 @@
-
 hostprogs-y	:= mk_sc mk_thread
 always		:= $(hostprogs-y)
 
-mk_thread-objs	:= mk_thread_kern.o mk_thread_user.o
-
-HOSTCFLAGS_mk_thread_kern.o	:= $(CFLAGS) $(CPPFLAGS)
-HOSTCFLAGS_mk_thread_user.o	:= $(USER_CFLAGS)
+HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um
+HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um
diff --git a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c
index 85cbd30..04c0d73 100644
--- a/arch/um/sys-i386/util/mk_sc.c
+++ b/arch/um/sys-i386/util/mk_sc.c
@@ -1,52 +1,51 @@
 #include <stdio.h>
-#include <signal.h>
-#include <linux/stddef.h>
+#include <user-offsets.h>
 
 #define SC_OFFSET(name, field) \
-  printf("#define " name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
-	 offsetof(struct sigcontext, field))
+  printf("#define " #name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
+	 name)
 
 #define SC_FP_OFFSET(name, field) \
-  printf("#define " name \
+  printf("#define " #name \
 	 "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-	 offsetof(struct _fpstate, field))
+	 name)
 
 #define SC_FP_OFFSET_PTR(name, field, type) \
-  printf("#define " name \
+  printf("#define " #name \
 	 "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-	 offsetof(struct _fpstate, field))
+	 name)
 
 int main(int argc, char **argv)
 {
-  SC_OFFSET("SC_IP", eip);
-  SC_OFFSET("SC_SP", esp);
-  SC_OFFSET("SC_FS", fs);
-  SC_OFFSET("SC_GS", gs);
-  SC_OFFSET("SC_DS", ds);
-  SC_OFFSET("SC_ES", es);
-  SC_OFFSET("SC_SS", ss);
-  SC_OFFSET("SC_CS", cs);
-  SC_OFFSET("SC_EFLAGS", eflags);
-  SC_OFFSET("SC_EAX", eax);
-  SC_OFFSET("SC_EBX", ebx);
-  SC_OFFSET("SC_ECX", ecx);
-  SC_OFFSET("SC_EDX", edx);
-  SC_OFFSET("SC_EDI", edi);
-  SC_OFFSET("SC_ESI", esi);
-  SC_OFFSET("SC_EBP", ebp);
-  SC_OFFSET("SC_TRAPNO", trapno);
-  SC_OFFSET("SC_ERR", err);
-  SC_OFFSET("SC_CR2", cr2);
-  SC_OFFSET("SC_FPSTATE", fpstate);
-  SC_OFFSET("SC_SIGMASK", oldmask);
-  SC_FP_OFFSET("SC_FP_CW", cw);
-  SC_FP_OFFSET("SC_FP_SW", sw);
-  SC_FP_OFFSET("SC_FP_TAG", tag);
-  SC_FP_OFFSET("SC_FP_IPOFF", ipoff);
-  SC_FP_OFFSET("SC_FP_CSSEL", cssel);
-  SC_FP_OFFSET("SC_FP_DATAOFF", dataoff);
-  SC_FP_OFFSET("SC_FP_DATASEL", datasel);
-  SC_FP_OFFSET_PTR("SC_FP_ST", _st, "struct _fpstate");
-  SC_FP_OFFSET_PTR("SC_FXSR_ENV", _fxsr_env, "void");
+  SC_OFFSET(SC_IP, eip);
+  SC_OFFSET(SC_SP, esp);
+  SC_OFFSET(SC_FS, fs);
+  SC_OFFSET(SC_GS, gs);
+  SC_OFFSET(SC_DS, ds);
+  SC_OFFSET(SC_ES, es);
+  SC_OFFSET(SC_SS, ss);
+  SC_OFFSET(SC_CS, cs);
+  SC_OFFSET(SC_EFLAGS, eflags);
+  SC_OFFSET(SC_EAX, eax);
+  SC_OFFSET(SC_EBX, ebx);
+  SC_OFFSET(SC_ECX, ecx);
+  SC_OFFSET(SC_EDX, edx);
+  SC_OFFSET(SC_EDI, edi);
+  SC_OFFSET(SC_ESI, esi);
+  SC_OFFSET(SC_EBP, ebp);
+  SC_OFFSET(SC_TRAPNO, trapno);
+  SC_OFFSET(SC_ERR, err);
+  SC_OFFSET(SC_CR2, cr2);
+  SC_OFFSET(SC_FPSTATE, fpstate);
+  SC_OFFSET(SC_SIGMASK, oldmask);
+  SC_FP_OFFSET(SC_FP_CW, cw);
+  SC_FP_OFFSET(SC_FP_SW, sw);
+  SC_FP_OFFSET(SC_FP_TAG, tag);
+  SC_FP_OFFSET(SC_FP_IPOFF, ipoff);
+  SC_FP_OFFSET(SC_FP_CSSEL, cssel);
+  SC_FP_OFFSET(SC_FP_DATAOFF, dataoff);
+  SC_FP_OFFSET(SC_FP_DATASEL, datasel);
+  SC_FP_OFFSET_PTR(SC_FP_ST, _st, "struct _fpstate");
+  SC_FP_OFFSET_PTR(SC_FXSR_ENV, _fxsr_env, "void");
   return(0);
 }
diff --git a/arch/um/sys-i386/util/mk_thread.c b/arch/um/sys-i386/util/mk_thread.c
new file mode 100644
index 0000000..7470d0d
--- /dev/null
+++ b/arch/um/sys-i386/util/mk_thread.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <kernel-offsets.h>
+
+int main(int argc, char **argv)
+{
+  printf("/*\n");
+  printf(" * Generated by mk_thread\n");
+  printf(" */\n");
+  printf("\n");
+  printf("#ifndef __UM_THREAD_H\n");
+  printf("#define __UM_THREAD_H\n");
+  printf("\n");
+  printf("#define TASK_DEBUGREGS(task) ((unsigned long *) "
+	 "&(((char *) (task))[%d]))\n", TASK_DEBUGREGS);
+#ifdef TASK_EXTERN_PID
+  printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n",
+	 TASK_EXTERN_PID);
+#endif
+  printf("\n");
+  printf("#endif\n");
+  return(0);
+}
diff --git a/arch/um/sys-i386/util/mk_thread_kern.c b/arch/um/sys-i386/util/mk_thread_kern.c
deleted file mode 100644
index 948b1ce..0000000
--- a/arch/um/sys-i386/util/mk_thread_kern.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "linux/config.h"
-#include "linux/stddef.h"
-#include "linux/sched.h"
-
-extern void print_head(void);
-extern void print_constant_ptr(char *name, int value);
-extern void print_constant(char *name, char *type, int value);
-extern void print_tail(void);
-
-#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
-
-int main(int argc, char **argv)
-{
-  print_head();
-  print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs));
-#ifdef CONFIG_MODE_TT
-  print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
-#endif
-  print_tail();
-  return(0);
-}
-
diff --git a/arch/um/sys-i386/util/mk_thread_user.c b/arch/um/sys-i386/util/mk_thread_user.c
deleted file mode 100644
index 2620cd6..0000000
--- a/arch/um/sys-i386/util/mk_thread_user.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <stdio.h>
-
-void print_head(void)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_thread\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_THREAD_H\n");
-  printf("#define __UM_THREAD_H\n");
-  printf("\n");
-}
-
-void print_constant_ptr(char *name, int value)
-{
-  printf("#define %s(task) ((unsigned long *) "
-	 "&(((char *) (task))[%d]))\n", name, value);
-}
-
-void print_constant(char *name, char *type, int value)
-{
-  printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, 
-	 value);
-}
-
-void print_tail(void)
-{
-  printf("\n");
-  printf("#endif\n");
-}
diff --git a/arch/um/sys-ppc/ptrace.c b/arch/um/sys-ppc/ptrace.c
index a971366d..8e71b47 100644
--- a/arch/um/sys-ppc/ptrace.c
+++ b/arch/um/sys-ppc/ptrace.c
@@ -8,6 +8,25 @@
 	return 0;
 }
 
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+
+	else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))){
+		  addr -= offsetof(struct user, u_debugreg[0]);
+		  addr = addr >> 2;
+		  if((addr == 4) || (addr == 5)) return -EIO;
+		  child->thread.arch.debugregs[addr] = data;
+		  return 0;
+	}
+	return -EIO;
+}
+
 unsigned long getreg(struct task_struct *child, unsigned long regno)
 {
 	unsigned long retval = ~0UL;
@@ -16,6 +35,27 @@
 	return retval;
 }
 
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	/* read the word at location addr in the USER area. */
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if(addr < MAX_REG_OFFSET){
+		tmp = getreg(child, addr);
+	}
+	else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))){
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long *) data);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 2129e31..3d7da91 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -4,24 +4,20 @@
 # Licensed under the GPL
 #
 
+#XXX: why into lib-y?
 lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
 	ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \
-	syscalls.o sysrq.o thunk.o
+	syscalls.o sysrq.o thunk.o syscall_table.o
+
+obj-y := ksyms.o
+obj-$(CONFIG_MODULES) += module.o um_module.o
 
 USER_OBJS := ptrace_user.o sigcontext.o
 
 include arch/um/scripts/Makefile.rules
 
 SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
-	semaphore.c thunk.S
-
-# this needs to be before the foreach, because clean-files does not accept
-# complete paths like $(src)/$f.
-clean-files := $(SYMLINKS)
-
-targets += $(SYMLINKS)
-
-SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f)
+	semaphore.c thunk.S module.c
 
 bitops.c-dir = lib
 csum-copy.S-dir = lib
@@ -30,8 +26,8 @@
 memcpy.S-dir = lib
 semaphore.c-dir = kernel
 thunk.S-dir = lib
-
-$(SYMLINKS): FORCE
-	$(call if_changed,make_link)
+module.c-dir = kernel
 
 CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
+
+subdir- := util
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index f3b5187..651332a 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -5,7 +5,9 @@
  * Licensed under the GPL
  */
 
+#include "linux/delay.h"
 #include "asm/processor.h"
+#include "asm/param.h"
 
 void __delay(unsigned long loops)
 {
@@ -14,6 +16,22 @@
 	for(i = 0; i < loops; i++) ;
 }
 
+void __udelay(unsigned long usecs)
+{
+	int i, n;
+
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
+	for(i=0;i<n;i++) ;
+}
+
+void __const_udelay(unsigned long usecs)
+{
+	int i, n;
+
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
+	for(i=0;i<n;i++) ;
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/sys-x86_64/kernel-offsets.c
new file mode 100644
index 0000000..220e875
--- /dev/null
+++ b/arch/um/sys-x86_64/kernel-offsets.c
@@ -0,0 +1,24 @@
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <asm/page.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define DEFINE_STR1(x) #x
+#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+#ifdef CONFIG_MODE_TT
+	OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
+#endif
+#include <common-offsets.h>
+}
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
new file mode 100644
index 0000000..a27f0ee
--- /dev/null
+++ b/arch/um/sys-x86_64/ksyms.c
@@ -0,0 +1,20 @@
+#include "linux/module.h"
+#include "linux/in6.h"
+#include "linux/rwsem.h"
+#include "asm/byteorder.h"
+#include "asm/semaphore.h"
+#include "asm/uaccess.h"
+#include "asm/checksum.h"
+#include "asm/errno.h"
+
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
+
+/*XXX: we need them because they would be exported by x86_64 */
+EXPORT_SYMBOL(__memcpy);
+
+/* Networking helper routines. */
+/*EXPORT_SYMBOL(csum_partial_copy_from);
+EXPORT_SYMBOL(csum_partial_copy_to);*/
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 8c146b2..b593bb2 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -62,6 +62,27 @@
 	return 0;
 }
 
+int poke_user(struct task_struct *child, long addr, long data)
+{
+        if ((addr & 3) || addr < 0)
+                return -EIO;
+
+        if (addr < MAX_REG_OFFSET)
+                return putreg(child, addr, data);
+
+#if 0 /* Need x86_64 debugregs handling */
+        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+                (addr <= offsetof(struct user, u_debugreg[7]))){
+                addr -= offsetof(struct user, u_debugreg[0]);
+                addr = addr >> 2;
+                if((addr == 4) || (addr == 5)) return -EIO;
+                child->thread.arch.debugregs[addr] = data;
+                return 0;
+        }
+#endif
+        return -EIO;
+}
+
 unsigned long getreg(struct task_struct *child, int regno)
 {
 	unsigned long retval = ~0UL;
@@ -84,6 +105,29 @@
 	return retval;
 }
 
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	/* read the word at location addr in the USER area. */
+        unsigned long tmp;
+
+        if ((addr & 3) || addr < 0)
+                return -EIO;
+
+        tmp = 0;  /* Default return condition */
+        if(addr < MAX_REG_OFFSET){
+                tmp = getreg(child, addr);
+        }
+#if 0 /* Need x86_64 debugregs handling */
+        else if((addr >= offsetof(struct user, u_debugreg[0])) &&
+                (addr <= offsetof(struct user, u_debugreg[7]))){
+                addr -= offsetof(struct user, u_debugreg[0]);
+                addr = addr >> 2;
+                tmp = child->thread.arch.debugregs[addr];
+        }
+#endif
+        return put_user(tmp, (unsigned long *) data);
+}
+
 void arch_switch(void)
 {
 /* XXX
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 5bc5a0d..73a7926 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -57,7 +57,7 @@
 int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
                         struct pt_regs *regs, unsigned long mask)
 {
-	unsigned long eflags;
+        struct faultinfo * fi = &current->thread.arch.faultinfo;
 	int err = 0;
 
 	err |= __put_user(0, &to->gs);
@@ -84,14 +84,16 @@
 	err |= PUTREG(regs, R14, to, r14);
 	err |= PUTREG(regs, R15, to, r15);
 	err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
-	err |= __put_user(current->thread.err, &to->err);
-	err |= __put_user(current->thread.trap_no, &to->trapno);
+
+        err |= __put_user(fi->cr2, &to->cr2);
+        err |= __put_user(fi->error_code, &to->err);
+        err |= __put_user(fi->trap_no, &to->trapno);
+
 	err |= PUTREG(regs, RIP, to, rip);
 	err |= PUTREG(regs, EFLAGS, to, eflags);
 #undef PUTREG
 
 	err |= __put_user(mask, &to->oldmask);
-	err |= __put_user(current->thread.cr2, &to->cr2);
 
 	return(err);
 }
@@ -166,7 +168,7 @@
 
 	frame = (struct rt_sigframe __user *)
 		round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
-	frame -= 128;
+	((unsigned char *) frame) -= 128;
 
 	if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
 		goto out;
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
new file mode 100644
index 0000000..34b2e84
--- /dev/null
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -0,0 +1,59 @@
+/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML. */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+#include <linux/config.h>
+
+#define __NO_STUBS
+
+/* Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table. */
+
+/* Not going to be implemented by UML, since we have no hardware. */
+#define stub_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+/* The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility. */
+/*#define sys_set_thread_area sys_ni_syscall
+#define sys_get_thread_area sys_ni_syscall*/
+
+/* For __NR_time. The x86-64 name hopefully will change from sys_time64 to
+ * sys_time (since the current situation is bogus). I've sent a patch to cleanup
+ * this. Remove below the obsoleted line. */
+#define sys_time64 um_time
+#define sys_time um_time
+
+/* On UML we call it this way ("old" means it's not mmap2) */
+#define sys_mmap old_mmap
+/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
+ * See arch/x86_64/kernel/sys_x86_64.c */
+#define sys_uname sys_uname64
+
+#define stub_clone sys_clone
+#define stub_fork sys_fork
+#define stub_vfork sys_vfork
+#define stub_execve sys_execve
+#define stub_rt_sigsuspend sys_rt_sigsuspend
+#define stub_sigaltstack sys_sigaltstack
+#define stub_rt_sigreturn sys_rt_sigreturn
+
+#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+#undef _ASM_X86_64_UNISTD_H_
+#include <asm-x86_64/unistd.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, sym) [ nr ] = sym,
+#undef _ASM_X86_64_UNISTD_H_
+
+typedef void (*sys_call_ptr_t)(void);
+
+extern void sys_ni_syscall(void);
+
+sys_call_ptr_t sys_call_table[__NR_syscall_max+1] __cacheline_aligned = {
+	/* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
+	[0 ... __NR_syscall_max] = &sys_ni_syscall,
+#include <asm-x86_64/unistd.h>
+};
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 68205a0..dd99146 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -7,6 +7,8 @@
 #include "linux/linkage.h"
 #include "linux/slab.h"
 #include "linux/shm.h"
+#include "linux/utsname.h"
+#include "linux/personality.h"
 #include "asm/uaccess.h"
 #define __FRAME_OFFSETS
 #include "asm/ptrace.h"
@@ -14,11 +16,15 @@
 #include "asm/prctl.h" /* XXX This should get the constants from libc */
 #include "choose-mode.h"
 
-asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg)
+asmlinkage long sys_uname64(struct new_utsname __user * name)
 {
-	unsigned long raddr;
-
-	return do_shmat(shmid, shmaddr, shmflg, &raddr) ?: (long) raddr;
+	int err;
+	down_read(&uts_sem);
+	err = copy_to_user(name, &system_utsname, sizeof (*name));
+	up_read(&uts_sem);
+	if (personality(current->personality) == PER_LINUX32)
+		err |= copy_to_user(&name->machine, "i686", 5);
+	return err ? -EFAULT : 0;
 }
 
 #ifdef CONFIG_MODE_TT
@@ -38,6 +44,8 @@
 #ifdef CONFIG_MODE_SKAS
 extern int userspace_pid[];
 
+#include "skas_ptrace.h"
+
 long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
 {
 	struct ptrace_ldt ldt;
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
new file mode 100644
index 0000000..8b8eff1
--- /dev/null
+++ b/arch/um/sys-x86_64/um_module.c
@@ -0,0 +1,19 @@
+#include <linux/vmalloc.h>
+#include <linux/moduleloader.h>
+
+/*Copied from i386 arch/i386/kernel/module.c */
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc_exec(size);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
new file mode 100644
index 0000000..5e14792
--- /dev/null
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <signal.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+	OFFSET(SC_RBX, sigcontext, rbx);
+	OFFSET(SC_RCX, sigcontext, rcx);
+	OFFSET(SC_RDX, sigcontext, rdx);
+	OFFSET(SC_RSI, sigcontext, rsi);
+	OFFSET(SC_RDI, sigcontext, rdi);
+	OFFSET(SC_RBP, sigcontext, rbp);
+	OFFSET(SC_RAX, sigcontext, rax);
+	OFFSET(SC_R8, sigcontext, r8);
+	OFFSET(SC_R9, sigcontext, r9);
+	OFFSET(SC_R10, sigcontext, r10);
+	OFFSET(SC_R11, sigcontext, r11);
+	OFFSET(SC_R12, sigcontext, r12);
+	OFFSET(SC_R13, sigcontext, r13);
+	OFFSET(SC_R14, sigcontext, r14);
+	OFFSET(SC_R15, sigcontext, r15);
+	OFFSET(SC_IP, sigcontext, rip);
+	OFFSET(SC_SP, sigcontext, rsp);
+	OFFSET(SC_CR2, sigcontext, cr2);
+	OFFSET(SC_ERR, sigcontext, err);
+	OFFSET(SC_TRAPNO, sigcontext, trapno);
+	OFFSET(SC_CS, sigcontext, cs);
+	OFFSET(SC_FS, sigcontext, fs);
+	OFFSET(SC_GS, sigcontext, gs);
+	OFFSET(SC_EFLAGS, sigcontext, eflags);
+	OFFSET(SC_SIGMASK, sigcontext, oldmask);
+#if 0
+	OFFSET(SC_ORIG_RAX, sigcontext, orig_rax);
+	OFFSET(SC_DS, sigcontext, ds);
+	OFFSET(SC_ES, sigcontext, es);
+	OFFSET(SC_SS, sigcontext, ss);
+#endif
+
+	DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
+	DEFINE(HOST_RBX, RBX);
+	DEFINE(HOST_RCX, RCX);
+	DEFINE(HOST_RDI, RDI);
+	DEFINE(HOST_RSI, RSI);
+	DEFINE(HOST_RDX, RDX);
+	DEFINE(HOST_RBP, RBP);
+	DEFINE(HOST_RAX, RAX);
+	DEFINE(HOST_R8, R8);
+	DEFINE(HOST_R9, R9);
+	DEFINE(HOST_R10, R10);
+	DEFINE(HOST_R11, R11);
+	DEFINE(HOST_R12, R12);
+	DEFINE(HOST_R13, R13);
+	DEFINE(HOST_R14, R14);
+	DEFINE(HOST_R15, R15);
+	DEFINE(HOST_ORIG_RAX, ORIG_RAX);
+	DEFINE(HOST_CS, CS);
+	DEFINE(HOST_SS, SS);
+	DEFINE(HOST_EFLAGS, EFLAGS);
+#if 0
+	DEFINE(HOST_FS, FS);
+	DEFINE(HOST_GS, GS);
+	DEFINE(HOST_DS, DS);
+	DEFINE(HOST_ES, ES);
+#endif
+
+	DEFINE(HOST_IP, RIP);
+	DEFINE(HOST_SP, RSP);
+	DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+}
diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile
index 0026079..75b052c 100644
--- a/arch/um/sys-x86_64/util/Makefile
+++ b/arch/um/sys-x86_64/util/Makefile
@@ -4,7 +4,5 @@
 hostprogs-y	:= mk_sc mk_thread
 always		:= $(hostprogs-y)
 
-mk_thread-objs	:= mk_thread_kern.o mk_thread_user.o
-
-HOSTCFLAGS_mk_thread_kern.o	:= $(CFLAGS) $(CPPFLAGS)
-HOSTCFLAGS_mk_thread_user.o	:= $(USER_CFLAGS)
+HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um
+HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um
diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c
index c236e21..7619bc3 100644
--- a/arch/um/sys-x86_64/util/mk_sc.c
+++ b/arch/um/sys-x86_64/util/mk_sc.c
@@ -3,56 +3,45 @@
  */
 
 #include <stdio.h>
-#include <signal.h>
-#include <linux/stddef.h>
+#include <user-offsets.h>
 
-#define SC_OFFSET(name, field) \
-  printf("#define " name \
-	 "(sc) *((unsigned long *) &(((char *) (sc))[%ld]))\n",\
-	 offsetof(struct sigcontext, field))
-
-#define SC_FP_OFFSET(name, field) \
-  printf("#define " name \
-	 "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%ld]))\n",\
-	 offsetof(struct _fpstate, field))
-
-#define SC_FP_OFFSET_PTR(name, field, type) \
-  printf("#define " name \
-	 "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-	 offsetof(struct _fpstate, field))
+#define SC_OFFSET(name) \
+  printf("#define " #name \
+	 "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
+	 name)
 
 int main(int argc, char **argv)
 {
-  SC_OFFSET("SC_RBX", rbx);
-  SC_OFFSET("SC_RCX", rcx);
-  SC_OFFSET("SC_RDX", rdx);
-  SC_OFFSET("SC_RSI", rsi);
-  SC_OFFSET("SC_RDI", rdi);
-  SC_OFFSET("SC_RBP", rbp);
-  SC_OFFSET("SC_RAX", rax);
-  SC_OFFSET("SC_R8", r8);
-  SC_OFFSET("SC_R9", r9);
-  SC_OFFSET("SC_R10", r10);
-  SC_OFFSET("SC_R11", r11);
-  SC_OFFSET("SC_R12", r12);
-  SC_OFFSET("SC_R13", r13);
-  SC_OFFSET("SC_R14", r14);
-  SC_OFFSET("SC_R15", r15);
-  SC_OFFSET("SC_IP", rip);
-  SC_OFFSET("SC_SP", rsp);
-  SC_OFFSET("SC_CR2", cr2);
-  SC_OFFSET("SC_ERR", err);
-  SC_OFFSET("SC_TRAPNO", trapno);
-  SC_OFFSET("SC_CS", cs);
-  SC_OFFSET("SC_FS", fs);
-  SC_OFFSET("SC_GS", gs);
-  SC_OFFSET("SC_EFLAGS", eflags);
-  SC_OFFSET("SC_SIGMASK", oldmask);
+  SC_OFFSET(SC_RBX);
+  SC_OFFSET(SC_RCX);
+  SC_OFFSET(SC_RDX);
+  SC_OFFSET(SC_RSI);
+  SC_OFFSET(SC_RDI);
+  SC_OFFSET(SC_RBP);
+  SC_OFFSET(SC_RAX);
+  SC_OFFSET(SC_R8);
+  SC_OFFSET(SC_R9);
+  SC_OFFSET(SC_R10);
+  SC_OFFSET(SC_R11);
+  SC_OFFSET(SC_R12);
+  SC_OFFSET(SC_R13);
+  SC_OFFSET(SC_R14);
+  SC_OFFSET(SC_R15);
+  SC_OFFSET(SC_IP);
+  SC_OFFSET(SC_SP);
+  SC_OFFSET(SC_CR2);
+  SC_OFFSET(SC_ERR);
+  SC_OFFSET(SC_TRAPNO);
+  SC_OFFSET(SC_CS);
+  SC_OFFSET(SC_FS);
+  SC_OFFSET(SC_GS);
+  SC_OFFSET(SC_EFLAGS);
+  SC_OFFSET(SC_SIGMASK);
 #if 0
-  SC_OFFSET("SC_ORIG_RAX", orig_rax);
-  SC_OFFSET("SC_DS", ds);
-  SC_OFFSET("SC_ES", es);
-  SC_OFFSET("SC_SS", ss);
+  SC_OFFSET(SC_ORIG_RAX);
+  SC_OFFSET(SC_DS);
+  SC_OFFSET(SC_ES);
+  SC_OFFSET(SC_SS);
 #endif
   return(0);
 }
diff --git a/arch/um/sys-x86_64/util/mk_thread.c b/arch/um/sys-x86_64/util/mk_thread.c
new file mode 100644
index 0000000..1551739
--- /dev/null
+++ b/arch/um/sys-x86_64/util/mk_thread.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <kernel-offsets.h>
+
+int main(int argc, char **argv)
+{
+  printf("/*\n");
+  printf(" * Generated by mk_thread\n");
+  printf(" */\n");
+  printf("\n");
+  printf("#ifndef __UM_THREAD_H\n");
+  printf("#define __UM_THREAD_H\n");
+  printf("\n");
+#ifdef TASK_EXTERN_PID
+  printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n",
+	 TASK_EXTERN_PID);
+#endif
+  printf("\n");
+  printf("#endif\n");
+  return(0);
+}
diff --git a/arch/um/sys-x86_64/util/mk_thread_kern.c b/arch/um/sys-x86_64/util/mk_thread_kern.c
deleted file mode 100644
index a281673..0000000
--- a/arch/um/sys-x86_64/util/mk_thread_kern.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "linux/config.h"
-#include "linux/stddef.h"
-#include "linux/sched.h"
-
-extern void print_head(void);
-extern void print_constant_ptr(char *name, int value);
-extern void print_constant(char *name, char *type, int value);
-extern void print_tail(void);
-
-#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
-
-int main(int argc, char **argv)
-{
-  print_head();
-#ifdef CONFIG_MODE_TT
-  print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
-#endif
-  print_tail();
-  return(0);
-}
-
diff --git a/arch/um/sys-x86_64/util/mk_thread_user.c b/arch/um/sys-x86_64/util/mk_thread_user.c
deleted file mode 100644
index 7989725..0000000
--- a/arch/um/sys-x86_64/util/mk_thread_user.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <stdio.h>
-
-void print_head(void)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_thread\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_THREAD_H\n");
-  printf("#define __UM_THREAD_H\n");
-  printf("\n");
-}
-
-void print_constant_ptr(char *name, int value)
-{
-  printf("#define %s(task) ((unsigned long *) "
-	 "&(((char *) (task))[%d]))\n", name, value);
-}
-
-void print_constant(char *name, char *type, int value)
-{
-  printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
-	 value);
-}
-
-void print_tail(void)
-{
-  printf("\n");
-  printf("#endif\n");
-}
diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile
index e2ab712..4c7551c 100644
--- a/arch/um/util/Makefile
+++ b/arch/um/util/Makefile
@@ -1,8 +1,5 @@
 hostprogs-y		:= mk_task mk_constants
 always			:= $(hostprogs-y)
 
-mk_task-objs		:= mk_task_user.o mk_task_kern.o
-mk_constants-objs	:= mk_constants_user.o mk_constants_kern.o
-
-HOSTCFLAGS_mk_task_kern.o	:= $(CFLAGS) $(CPPFLAGS)
-HOSTCFLAGS_mk_constants_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_task.o := -I$(objtree)/arch/um
+HOSTCFLAGS_mk_constants.o := -I$(objtree)/arch/um
diff --git a/arch/um/util/mk_constants.c b/arch/um/util/mk_constants.c
new file mode 100644
index 0000000..ab217be
--- /dev/null
+++ b/arch/um/util/mk_constants.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <kernel-offsets.h>
+
+#define SHOW_INT(sym) printf("#define %s %d\n", #sym, sym)
+#define SHOW_STR(sym) printf("#define %s %s\n", #sym, sym)
+
+int main(int argc, char **argv)
+{
+  printf("/*\n");
+  printf(" * Generated by mk_constants\n");
+  printf(" */\n");
+  printf("\n");
+  printf("#ifndef __UM_CONSTANTS_H\n");
+  printf("#define __UM_CONSTANTS_H\n");
+  printf("\n");
+
+  SHOW_INT(UM_KERN_PAGE_SIZE);
+
+  SHOW_STR(UM_KERN_EMERG);
+  SHOW_STR(UM_KERN_ALERT);
+  SHOW_STR(UM_KERN_CRIT);
+  SHOW_STR(UM_KERN_ERR);
+  SHOW_STR(UM_KERN_WARNING);
+  SHOW_STR(UM_KERN_NOTICE);
+  SHOW_STR(UM_KERN_INFO);
+  SHOW_STR(UM_KERN_DEBUG);
+
+  SHOW_INT(UM_NSEC_PER_SEC);
+  printf("\n");
+  printf("#endif\n");
+  return(0);
+}
diff --git a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c
deleted file mode 100644
index cdcb123..0000000
--- a/arch/um/util/mk_constants_kern.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "linux/kernel.h"
-#include "linux/stringify.h"
-#include "linux/time.h"
-#include "asm/page.h"
-
-extern void print_head(void);
-extern void print_constant_str(char *name, char *value);
-extern void print_constant_int(char *name, int value);
-extern void print_tail(void);
-
-int main(int argc, char **argv)
-{
-  print_head();
-  print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
-
-  print_constant_str("UM_KERN_EMERG", KERN_EMERG);
-  print_constant_str("UM_KERN_ALERT", KERN_ALERT);
-  print_constant_str("UM_KERN_CRIT", KERN_CRIT);
-  print_constant_str("UM_KERN_ERR", KERN_ERR);
-  print_constant_str("UM_KERN_WARNING", KERN_WARNING);
-  print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
-  print_constant_str("UM_KERN_INFO", KERN_INFO);
-  print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
-
-  print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
-  print_tail();
-  return(0);
-}
diff --git a/arch/um/util/mk_constants_user.c b/arch/um/util/mk_constants_user.c
deleted file mode 100644
index 8f4d7e5..0000000
--- a/arch/um/util/mk_constants_user.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <stdio.h>
-
-void print_head(void)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_constants\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_CONSTANTS_H\n");
-  printf("#define __UM_CONSTANTS_H\n");
-  printf("\n");
-}
-
-void print_constant_str(char *name, char *value)
-{
-  printf("#define %s \"%s\"\n", name, value);
-}
-
-void print_constant_int(char *name, int value)
-{
-  printf("#define %s %d\n", name, value);
-}
-
-void print_tail(void)
-{
-  printf("\n");
-  printf("#endif\n");
-}
diff --git a/arch/um/util/mk_task_user.c b/arch/um/util/mk_task.c
similarity index 75%
rename from arch/um/util/mk_task_user.c
rename to arch/um/util/mk_task.c
index 9db849f..36c9606 100644
--- a/arch/um/util/mk_task_user.c
+++ b/arch/um/util/mk_task.c
@@ -1,10 +1,5 @@
 #include <stdio.h>
-
-void print(char *name, char *type, int offset)
-{
-  printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
-	 offset);
-}
+#include <kernel-offsets.h>
 
 void print_ptr(char *name, char *type, int offset)
 {
@@ -12,7 +7,13 @@
 	 offset);
 }
 
-void print_head(void)
+void print(char *name, char *type, int offset)
+{
+  printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
+	 offset);
+}
+
+int main(int argc, char **argv)
 {
   printf("/*\n");
   printf(" * Generated by mk_task\n");
@@ -21,10 +22,9 @@
   printf("#ifndef __TASK_H\n");
   printf("#define __TASK_H\n");
   printf("\n");
-}
-
-void print_tail(void)
-{
+  print_ptr("TASK_REGS", "union uml_pt_regs", TASK_REGS);
+  print("TASK_PID", "int", TASK_PID);
   printf("\n");
   printf("#endif\n");
+  return(0);
 }
diff --git a/arch/um/util/mk_task_kern.c b/arch/um/util/mk_task_kern.c
deleted file mode 100644
index c218103..0000000
--- a/arch/um/util/mk_task_kern.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "linux/sched.h"
-#include "linux/stddef.h"
-
-extern void print(char *name, char *type, int offset);
-extern void print_ptr(char *name, char *type, int offset);
-extern void print_head(void);
-extern void print_tail(void);
-
-int main(int argc, char **argv)
-{
-  print_head();
-  print_ptr("TASK_REGS", "union uml_pt_regs", 
-	    offsetof(struct task_struct, thread.regs));
-  print("TASK_PID", "int", offsetof(struct task_struct, pid));
-  print_tail();
-  return(0);
-}
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index 8fa7807..4726b87 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/ptrace.h>
+#include <linux/signal.h>
 
 #include <asm/errno.h>
 #include <asm/ptrace.h>
@@ -208,7 +209,7 @@
 	/* Execute a single instruction. */
 	case PTRACE_SINGLESTEP:
 		rval = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 
 		/* Turn CHILD's single-step flag on or off.  */
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 80c38c5..44ee7f6 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -379,6 +379,11 @@
 	bool
 	default y
 
+# we have no ISA slots, but we do have ISA-style DMA.
+config ISA_DMA_API
+	bool
+	default y
+
 menu "Power management options"
 
 source kernel/power/Kconfig
diff --git a/arch/x86_64/boot/bootsect.S b/arch/x86_64/boot/bootsect.S
index bb15d40..011b7a4 100644
--- a/arch/x86_64/boot/bootsect.S
+++ b/arch/x86_64/boot/bootsect.S
@@ -63,7 +63,7 @@
 	jz	die
 	movb	$0xe, %ah
 	movw	$7, %bx
- 	int	$0x10
+	int	$0x10
 	jmp	msg_loop
 
 die:
@@ -71,7 +71,7 @@
 	xorw	%ax, %ax
 	int	$0x16
 	int	$0x19
-	
+
 	# int 0x19 should never return.  In case it does anyway,
 	# invoke the BIOS reset code...
 	ljmp	$0xf000,$0xfff0
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
index 3e838be..75d4d2a 100644
--- a/arch/x86_64/boot/setup.S
+++ b/arch/x86_64/boot/setup.S
@@ -160,7 +160,7 @@
 trampoline:	call	start_of_setup
 		.align 16
 					# The offset at this point is 0x240
-		.space  (0x7ff-0x240+1)	# E820 & EDD space (ending at 0x7ff)
+		.space  (0xeff-0x240+1)	# E820 & EDD space (ending at 0xeff)
 # End of setup header #####################################################
 
 start_of_setup:
@@ -412,9 +412,9 @@
 	# sizeof(e820rec).
 	#
 good820:
-	movb	(E820NR), %al			# up to 32 entries
+	movb	(E820NR), %al			# up to 128 entries
 	cmpb	$E820MAX, %al
-	jnl	bail820
+	jae	bail820
 
 	incb	(E820NR)
 	movw	%di, %ax
diff --git a/arch/x86_64/ia32/vsyscall.lds b/arch/x86_64/ia32/vsyscall.lds
index fa4b4dd..f2e75ed 100644
--- a/arch/x86_64/ia32/vsyscall.lds
+++ b/arch/x86_64/ia32/vsyscall.lds
@@ -36,6 +36,7 @@
 
   .text.rtsigreturn : { *(.text.rtsigreturn) }   :text =0x90909090
 	
+  .note		  : { *(.note.*) }		:text :note
   .eh_frame_hdr   : { *(.eh_frame_hdr) }	:text :eh_frame_hdr
   .eh_frame       : { KEEP (*(.eh_frame)) }	:text
   .dynamic        : { *(.dynamic) }		:text :dynamic
@@ -55,6 +56,7 @@
 {
   text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
   dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  note PT_NOTE FLAGS(4); /* PF_R */
   eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
 }
 
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 56516ac..7c154df 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -2,6 +2,12 @@
  * Handle the memory map.
  * The functions here do the job until bootmem takes over.
  * $Id: e820.c,v 1.4 2002/09/19 19:25:32 ak Exp $
+ *
+ *  Getting sanitize_e820_map() in sync with i386 version by applying change:
+ *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
+ *     Alex Achenbach <xela@slit.de>, December 2002.
+ *  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ *
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -277,7 +283,7 @@
 	int chgidx, still_changing;
 	int overlap_entries;
 	int new_bios_entry;
-	int old_nr, new_nr;
+	int old_nr, new_nr, chg_nr;
 	int i;
 
 	/*
@@ -331,20 +337,24 @@
 	for (i=0; i < 2*old_nr; i++)
 		change_point[i] = &change_point_list[i];
 
-	/* record all known change-points (starting and ending addresses) */
+	/* record all known change-points (starting and ending addresses),
+	   omitting those that are for empty memory regions */
 	chgidx = 0;
 	for (i=0; i < old_nr; i++)	{
-		change_point[chgidx]->addr = biosmap[i].addr;
-		change_point[chgidx++]->pbios = &biosmap[i];
-		change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
-		change_point[chgidx++]->pbios = &biosmap[i];
+		if (biosmap[i].size != 0) {
+			change_point[chgidx]->addr = biosmap[i].addr;
+			change_point[chgidx++]->pbios = &biosmap[i];
+			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+			change_point[chgidx++]->pbios = &biosmap[i];
+		}
 	}
+	chg_nr = chgidx;
 
 	/* sort change-point list by memory addresses (low -> high) */
 	still_changing = 1;
 	while (still_changing)	{
 		still_changing = 0;
-		for (i=1; i < 2*old_nr; i++)  {
+		for (i=1; i < chg_nr; i++)  {
 			/* if <current_addr> > <last_addr>, swap */
 			/* or, if current=<start_addr> & last=<end_addr>, swap */
 			if ((change_point[i]->addr < change_point[i-1]->addr) ||
@@ -367,7 +377,7 @@
 	last_type = 0;		 /* start with undefined memory type */
 	last_addr = 0;		 /* start with 0 as last starting address */
 	/* loop through change-points, determining affect on the new bios map */
-	for (chgidx=0; chgidx < 2*old_nr; chgidx++)
+	for (chgidx=0; chgidx < chg_nr; chgidx++)
 	{
 		/* keep track of all overlapping bios entries */
 		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 750bcd0..e3a19e8 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -60,7 +60,7 @@
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher */ 
 
-int early_serial_base = 0x3f8;  /* ttyS0 */ 
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY          0x20
 
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 3233a15..1086b5f 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -296,6 +296,7 @@
 	call syscall_trace_leave
 	popq %rdi
 	andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
+	cli
 	jmp int_restore_rest
 	
 int_signal:
@@ -307,6 +308,7 @@
 1:	movl $_TIF_NEED_RESCHED,%edi	
 int_restore_rest:
 	RESTORE_REST
+	cli
 	jmp int_with_check
 	CFI_ENDPROC
 		
@@ -490,7 +492,8 @@
 	call do_notify_resume
 	RESTORE_REST
 	cli
-	GET_THREAD_INFO(%rcx)	
+	GET_THREAD_INFO(%rcx)
+	movl $_TIF_WORK_MASK,%edi
 	jmp retint_check
 
 #ifdef CONFIG_PREEMPT
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 6cad46c..0f8c78d 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -29,8 +29,6 @@
 	       (unsigned long) __bss_end - (unsigned long) __bss_start);
 }
 
-extern char x86_boot_params[2048];
-
 #define NEW_CL_POINTER		0x228	/* Relative to real mode data */
 #define OLD_CL_MAGIC_ADDR	0x90020
 #define OLD_CL_MAGIC            0xA33F
@@ -44,7 +42,7 @@
 	int new_data;
 	char * command_line;
 
-	memcpy(x86_boot_params, real_mode_data, 2048); 
+	memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
 	new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
 	if (!new_data) {
 		if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
@@ -93,9 +91,6 @@
 #ifdef CONFIG_SMP
 	cpu_set(0, cpu_online_map);
 #endif
-	/* default console: */
-	if (!strstr(saved_command_line, "console="))
-		strcat(saved_command_line, " console=tty0"); 
 	s = strstr(saved_command_line, "earlyprintk=");
 	if (s != NULL)
 		setup_early_printk(s);
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 29a2572..60be586 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1607,7 +1607,6 @@
 				disable_8259A_irq(0);
 				setup_nmi();
 				enable_8259A_irq(0);
-				check_nmi_watchdog();
 			}
 			return;
 		}
@@ -1627,7 +1626,6 @@
 			nmi_watchdog_default();
 			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				check_nmi_watchdog();
 			}
 			return;
 		}
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 4f2a852..f77f8a0 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -355,6 +355,13 @@
 		*tos &= ~(TF_MASK | IF_MASK);
 		*tos |= kprobe_old_rflags;
 		break;
+	case 0xc3:		/* ret/lret */
+	case 0xcb:
+	case 0xc2:
+	case 0xca:
+		regs->eflags &= ~TF_MASK;
+		/* rip is already adjusted, no more changes required*/
+		return;
 	case 0xe8:		/* call relative - Fix return addr */
 		*tos = orig_rip + (*tos - copy_rip);
 		break;
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c
index c2ffea8..bac195c 100644
--- a/arch/x86_64/kernel/module.c
+++ b/arch/x86_64/kernel/module.c
@@ -30,9 +30,12 @@
 
 #define DEBUGP(fmt...) 
 
+#ifndef CONFIG_UML
 void module_free(struct module *mod, void *module_region)
 {
 	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
 }
 
 void *module_alloc(unsigned long size)
@@ -51,6 +54,7 @@
 
 	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
 }
+#endif
 
 /* We don't need anything special. */
 int module_frob_arch_sections(Elf_Ehdr *hdr,
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index e00d4ad..61de0b3 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -112,17 +112,20 @@
 	} 	
 }
 
-int __init check_nmi_watchdog (void)
+static int __init check_nmi_watchdog (void)
 {
 	int counts[NR_CPUS];
 	int cpu;
 
+	if (nmi_watchdog == NMI_NONE)
+		return 0;
+
 	if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic())  {
 		nmi_watchdog = NMI_NONE;
 		return -1; 
 	}	
 
-	printk(KERN_INFO "testing NMI watchdog ... ");
+	printk(KERN_INFO "Testing NMI watchdog ... ");
 
 	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		counts[cpu] = cpu_pda[cpu].__nmi_count; 
@@ -148,6 +151,8 @@
 
 	return 0;
 }
+/* Have this called later during boot so counters are updating */
+late_initcall(check_nmi_watchdog);
 
 int __init setup_nmi_watchdog(char *str)
 {
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 9922d2b..761b6d3 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -402,10 +402,10 @@
 	p->thread.fs = me->thread.fs;
 	p->thread.gs = me->thread.gs;
 
-	asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
-	asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
-	asm("movl %%es,%0" : "=m" (p->thread.es));
-	asm("movl %%ds,%0" : "=m" (p->thread.ds));
+	asm("mov %%gs,%0" : "=m" (p->thread.gsindex));
+	asm("mov %%fs,%0" : "=m" (p->thread.fsindex));
+	asm("mov %%es,%0" : "=m" (p->thread.es));
+	asm("mov %%ds,%0" : "=m" (p->thread.ds));
 
 	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
@@ -468,11 +468,11 @@
 	 * Switch DS and ES.
 	 * This won't pick up thread selector changes, but I guess that is ok.
 	 */
-	asm volatile("movl %%es,%0" : "=m" (prev->es)); 
+	asm volatile("mov %%es,%0" : "=m" (prev->es));
 	if (unlikely(next->es | prev->es))
 		loadsegment(es, next->es); 
 	
-	asm volatile ("movl %%ds,%0" : "=m" (prev->ds)); 
+	asm volatile ("mov %%ds,%0" : "=m" (prev->ds));
 	if (unlikely(next->ds | prev->ds))
 		loadsegment(ds, next->ds);
 
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index c701167..e26e86b 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -467,7 +468,7 @@
 	case PTRACE_CONT:    /* restart after signal. */
 
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
@@ -529,7 +530,7 @@
 
 	case PTRACE_SINGLESTEP:    /* set the trap flag. */
 		ret = -EIO;
-		if ((unsigned long) data > _NSIG)
+		if (!valid_signal(data))
 			break;
 		clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
 		set_singlestep(child);
@@ -634,20 +635,29 @@
 	/* do the secure computing check first */
 	secure_computing(regs->orig_rax);
 
-	if (unlikely(current->audit_context))
-		audit_syscall_entry(current, regs->orig_rax,
-				    regs->rdi, regs->rsi,
-				    regs->rdx, regs->r10);
-
 	if (test_thread_flag(TIF_SYSCALL_TRACE)
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace(regs);
+
+	if (unlikely(current->audit_context)) {
+		if (test_thread_flag(TIF_IA32)) {
+			audit_syscall_entry(current, AUDIT_ARCH_I386,
+					    regs->orig_rax,
+					    regs->rbx, regs->rcx,
+					    regs->rdx, regs->rsi);
+		} else {
+			audit_syscall_entry(current, AUDIT_ARCH_X86_64,
+					    regs->orig_rax,
+					    regs->rdi, regs->rsi,
+					    regs->rdx, regs->r10);
+		}
+	}
 }
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
 	if (unlikely(current->audit_context))
-		audit_syscall_exit(current, regs->rax);
+		audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax);
 
 	if ((test_thread_flag(TIF_SYSCALL_TRACE)
 	     || test_thread_flag(TIF_SINGLESTEP))
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index b18c114..2129cf9 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -977,7 +977,7 @@
 	if ((xlvl & 0xffff0000) == 0x80000000) {
 		if (xlvl >= 0x80000001) {
 			c->x86_capability[1] = cpuid_edx(0x80000001);
-			c->x86_capability[5] = cpuid_ecx(0x80000001);
+			c->x86_capability[6] = cpuid_ecx(0x80000001);
 		}
 		if (xlvl >= 0x80000004)
 			get_model_name(c); /* Default name */
@@ -1076,7 +1076,7 @@
 	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
 
 		/* AMD-defined */
-		"pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
 		NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
@@ -1100,11 +1100,17 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
+		/* VIA/Cyrix/Centaur-defined */
+		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
 		/* AMD-defined (#2) */
 		"lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
 	static char *x86_power_flags[] = { 
 		"ts",	/* temperature sensor */
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index b5305b0..678b7ac 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/bootmem.h>
 #include <linux/bitops.h>
+#include <asm/bootsetup.h>
 #include <asm/pda.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -26,7 +27,7 @@
 #include <asm/mman.h>
 #include <asm/numa.h>
 
-char x86_boot_params[2048] __initdata = {0,};
+char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
 
 cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
 
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index 7760224..d439ced 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -83,7 +83,7 @@
 
 struct rt_sigframe
 {
-	char *pretcode;
+	char __user *pretcode;
 	struct ucontext uc;
 	struct siginfo info;
 };
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index 477d8be..dbebd5c 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -152,12 +152,6 @@
 	return err ? -EFAULT : 0;
 }
 
-asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg)
-{
-	unsigned long raddr;
-	return do_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr;
-}
-
 asmlinkage long sys_time64(long __user * tloc)
 {
 	struct timeval now; 
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 88626e6..a43dedb 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -139,35 +139,23 @@
 #undef memmove
 #undef memchr
 #undef strlen
-#undef strcpy
 #undef strncmp
 #undef strncpy
 #undef strchr	
-#undef strcmp 
-#undef strcpy 
-#undef strcat
-#undef memcmp
 
 extern void * memset(void *,int,__kernel_size_t);
 extern size_t strlen(const char *);
 extern void * memmove(void * dest,const void *src,size_t count);
-extern char * strcpy(char * dest,const char *src);
-extern int strcmp(const char * cs,const char * ct);
 extern void *memchr(const void *s, int c, size_t n);
 extern void * memcpy(void *,const void *,__kernel_size_t);
 extern void * __memcpy(void *,const void *,__kernel_size_t);
-extern char * strcat(char *, const char *);
-extern int memcmp(const void * cs,const void * ct,size_t count);
 
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strncpy);
 EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(strrchr);
@@ -175,7 +163,6 @@
 EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
-EXPORT_SYMBOL(memcmp);
 
 #ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
 /* prototypes are wrong, these are assembly with custom calling functions */
diff --git a/arch/x86_64/lib/putuser.S b/arch/x86_64/lib/putuser.S
index d9d3e5e..5828b81 100644
--- a/arch/x86_64/lib/putuser.S
+++ b/arch/x86_64/lib/putuser.S
@@ -49,8 +49,8 @@
 	jc 20f
 	cmpq threadinfo_addr_limit(%r8),%rcx
 	jae 20f
-2:	decq %rcx
-	movw %dx,(%rcx)
+	decq %rcx
+2:	movw %dx,(%rcx)
 	xorl %eax,%eax
 	ret
 20:	decq %rcx
@@ -64,8 +64,8 @@
 	jc 30f
 	cmpq threadinfo_addr_limit(%r8),%rcx
 	jae 30f
-3:	subq $3,%rcx
-	movl %edx,(%rcx)
+	subq $3,%rcx
+3:	movl %edx,(%rcx)
 	xorl %eax,%eax
 	ret
 30:	subq $3,%rcx
@@ -79,8 +79,8 @@
 	jc 40f
 	cmpq threadinfo_addr_limit(%r8),%rcx
 	jae 40f
-4:	subq $7,%rcx
-	movq %rdx,(%rcx)
+	subq $7,%rcx
+4:	movq %rdx,(%rcx)
 	xorl %eax,%eax
 	ret
 40:	subq $7,%rcx
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 536754f..90d6089 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -146,7 +146,7 @@
 
 config CRYPTO_AES
 	tristate "AES cipher algorithms"
-	depends on CRYPTO && !(X86 && !X86_64)
+	depends on CRYPTO && !((X86 || UML_X86) && !64BIT)
 	help
 	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
 	  algorithm.
@@ -166,7 +166,7 @@
 
 config CRYPTO_AES_586
 	tristate "AES cipher algorithms (i586)"
-	depends on CRYPTO && (X86 && !X86_64)
+	depends on CRYPTO && ((X86 || UML_X86) && !64BIT)
 	help
 	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
 	  algorithm.
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 05a1781..ff64d33 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -838,7 +838,7 @@
 
 	/* Fall back to the default idle loop */
 	pm_idle = pm_idle_save;
-	synchronize_kernel();
+	synchronize_sched();  /* Relies on interrupts forcing exit from idle. */
 
 	pr->flags.power = 0;
 	result = acpi_processor_get_power_info(pr);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index e7ca066..119c940 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -379,8 +379,8 @@
 
 /**
  * setup_sys_fs_device_files - sets up the device files under device namespace
- * @@dev:	acpi_device object
- * @@func:	function pointer to create or destroy the device file
+ * @dev:	acpi_device object
+ * @func:	function pointer to create or destroy the device file
  */
 static void
 setup_sys_fs_device_files (
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 78e34ee..10da369 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -59,7 +59,6 @@
  * - doesn't support OAM cells
  * - eni_put_free may hang if not putting memory fragments that _complete_
  *   2^n block (never happens in real life, though)
- * - keeps IRQ even if initialization fails
  */
 
 
@@ -1802,22 +1801,22 @@
 	if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
 		    dev->number,eni_dev->irq);
-		return -EAGAIN;
+		error = -EAGAIN;
+		goto out;
 	}
-	/* @@@ should release IRQ on error */
 	pci_set_master(eni_dev->pci_dev);
 	if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
 	    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
 	    (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
 		    "master (0x%02x)\n",dev->number,error);
-		return error;
+		goto free_irq;
 	}
 	if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
 	    END_SWAP_DMA))) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
 		    "(0x%02x)\n",dev->number,error);
-		return error;
+		goto free_irq;
 	}
 	/* determine addresses of internal tables */
 	eni_dev->vci = eni_dev->ram;
@@ -1839,7 +1838,8 @@
 	if (!eni_dev->free_list) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
 		    dev->number);
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto free_irq;
 	}
 	eni_dev->free_len = 0;
 	eni_put_free(eni_dev,buf,buffer_mem);
@@ -1855,17 +1855,26 @@
 	 */
 	eni_out(0xffffffff,MID_IE);
 	error = start_tx(dev);
-	if (error) return error;
+	if (error) goto free_list;
 	error = start_rx(dev);
-	if (error) return error;
+	if (error) goto free_list;
 	error = dev->phy->start(dev);
-	if (error) return error;
+	if (error) goto free_list;
 	eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
 	    MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
 	    MID_MC_S);
 	    /* Tonga uses SBus INTReq1 */
 	(void) eni_in(MID_ISA); /* clear Midway interrupts */
 	return 0;
+
+free_list:
+	kfree(eni_dev->free_list);
+
+free_irq:
+	free_irq(eni_dev->irq, eni_dev);
+
+out:
+	return error;
 }
 
 
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 196b336..9e65bfb 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2792,8 +2792,6 @@
 
     fore200e = pci_get_drvdata(pci_dev);
 
-    list_del(&fore200e->entry);
-
     fore200e_shutdown(fore200e);
     kfree(fore200e);
     pci_disable_device(pci_dev);
@@ -2850,7 +2848,7 @@
     }
 
 #ifdef CONFIG_ATM_FORE200E_PCA
-    if (!pci_module_init(&fore200e_pca_driver))
+    if (!pci_register_driver(&fore200e_pca_driver))
 	return 0;
 #endif
 
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index c2c31a5..3022c54 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -70,6 +70,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
@@ -371,7 +372,7 @@
 
 	if (pci_enable_device(pci_dev))
 		return -EIO;
-	if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) {
+	if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK) != 0) {
 		printk(KERN_WARNING "he: no suitable dma available\n");
 		err = -EIO;
 		goto init_one_failure;
diff --git a/drivers/atm/he.h b/drivers/atm/he.h
index 1a90385..1dc2775 100644
--- a/drivers/atm/he.h
+++ b/drivers/atm/he.h
@@ -380,8 +380,6 @@
 #define PCI_VENDOR_ID_FORE	0x1127
 #define PCI_DEVICE_ID_FORE_HE	0x400
 
-#define HE_DMA_MASK		0xffffffff
-
 #define GEN_CNTL_0				0x40
 #define  INT_PROC_ENBL		(1<<25)
 #define  SLAVE_ENDIAN_MODE	(1<<16)
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index f4fa273..2b3902c 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -405,9 +405,8 @@
 
 static void driver_detach(struct device_driver * drv)
 {
-	struct list_head * entry, * next;
-	list_for_each_safe(entry, next, &drv->devices) {
-		struct device * dev = container_of(entry, struct device, driver_list);
+	while (!list_empty(&drv->devices)) {
+		struct device * dev = container_of(drv->devices.next, struct device, driver_list);
 		device_release_driver(dev);
 	}
 }
diff --git a/drivers/base/core.c b/drivers/base/core.c
index a7cedd8..268a9c8 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -139,7 +139,7 @@
 	buffer = &buffer[length];
 	buffer_size -= length;
 
-	if (dev->bus->hotplug) {
+	if (dev->bus && dev->bus->hotplug) {
 		/* have the bus specific function add its stuff */
 		retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
 			if (retval) {
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index cd64539..3a5f4c9 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -115,7 +115,7 @@
 
 /**
  *	platform_device_register - add a platform-level device
- *	@dev:	platform device we're adding
+ *	@pdev:	platform device we're adding
  *
  */
 int platform_device_register(struct platform_device * pdev)
@@ -174,7 +174,7 @@
 
 /**
  *	platform_device_unregister - remove a platform-level device
- *	@dev:	platform device we're removing
+ *	@pdev:	platform device we're removing
  *
  *	Note that this function will also release all memory- and port-based
  *	resources owned by the device (@dev->resource).
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 423bbf2..3760edf 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -3,6 +3,7 @@
   Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
 
   Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
+  Portions Copyright 2002 by Mylex (An IBM Business Unit)
 
   This program is free software; you may redistribute and/or modify it under
   the terms of the GNU General Public License Version 2 as published by the
@@ -532,6 +533,34 @@
   spin_lock_irq(&Controller->queue_lock);
 }
 
+/*
+  DAC960_GEM_QueueCommand queues Command for DAC960 GEM Series Controllers.
+*/
+
+static void DAC960_GEM_QueueCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
+  DAC960_V2_CommandMailbox_T *NextCommandMailbox =
+      Controller->V2.NextCommandMailbox;
+
+  CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
+  DAC960_GEM_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+
+  if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 ||
+      Controller->V2.PreviousCommandMailbox2->Words[0] == 0)
+      DAC960_GEM_MemoryMailboxNewCommand(ControllerBaseAddress);
+
+  Controller->V2.PreviousCommandMailbox2 =
+      Controller->V2.PreviousCommandMailbox1;
+  Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox;
+
+  if (++NextCommandMailbox > Controller->V2.LastCommandMailbox)
+      NextCommandMailbox = Controller->V2.FirstCommandMailbox;
+
+  Controller->V2.NextCommandMailbox = NextCommandMailbox;
+}
 
 /*
   DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers.
@@ -1464,6 +1493,17 @@
     					Controller->V2.FirstStatusMailboxDMA;
   switch (Controller->HardwareType)
     {
+    case DAC960_GEM_Controller:
+      while (DAC960_GEM_HardwareMailboxFullP(ControllerBaseAddress))
+	udelay(1);
+      DAC960_GEM_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA);
+      DAC960_GEM_HardwareMailboxNewCommand(ControllerBaseAddress);
+      while (!DAC960_GEM_HardwareMailboxStatusAvailableP(ControllerBaseAddress))
+	udelay(1);
+      CommandStatus = DAC960_GEM_ReadCommandStatus(ControllerBaseAddress);
+      DAC960_GEM_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+      DAC960_GEM_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+      break;
     case DAC960_BA_Controller:
       while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress))
 	udelay(1);
@@ -2627,6 +2667,9 @@
   if (Controller->MemoryMappedAddress) {
   	switch(Controller->HardwareType)
   	{
+		case DAC960_GEM_Controller:
+			DAC960_GEM_DisableInterrupts(Controller->BaseAddress);
+			break;
 		case DAC960_BA_Controller:
 			DAC960_BA_DisableInterrupts(Controller->BaseAddress);
 			break;
@@ -2705,6 +2748,9 @@
 
   switch (Controller->HardwareType)
   {
+	case DAC960_GEM_Controller:
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
+	  break;
 	case DAC960_BA_Controller:
 	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
@@ -2756,6 +2802,36 @@
   BaseAddress = Controller->BaseAddress;
   switch (Controller->HardwareType)
   {
+	case DAC960_GEM_Controller:
+	  DAC960_GEM_DisableInterrupts(BaseAddress);
+	  DAC960_GEM_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_GEM_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_GEM_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
+	  if (!DAC960_V2_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_GEM_EnableInterrupts(BaseAddress);
+	  Controller->QueueCommand = DAC960_GEM_QueueCommand;
+	  Controller->ReadControllerConfiguration =
+	    DAC960_V2_ReadControllerConfiguration;
+	  Controller->ReadDeviceConfiguration =
+	    DAC960_V2_ReadDeviceConfiguration;
+	  Controller->ReportDeviceConfiguration =
+	    DAC960_V2_ReportDeviceConfiguration;
+	  Controller->QueueReadWriteCommand =
+	    DAC960_V2_QueueReadWriteCommand;
+	  break;
 	case DAC960_BA_Controller:
 	  DAC960_BA_DisableInterrupts(BaseAddress);
 	  DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress);
@@ -5189,6 +5265,47 @@
   wake_up(&Controller->CommandWaitQueue);
 }
 
+/*
+  DAC960_GEM_InterruptHandler handles hardware interrupts from DAC960 GEM Series
+  Controllers.
+*/
+
+static irqreturn_t DAC960_GEM_InterruptHandler(int IRQ_Channel,
+				       void *DeviceIdentifier,
+				       struct pt_regs *InterruptRegisters)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_V2_StatusMailbox_T *NextStatusMailbox;
+  unsigned long flags;
+
+  spin_lock_irqsave(&Controller->queue_lock, flags);
+  DAC960_GEM_AcknowledgeInterrupt(ControllerBaseAddress);
+  NextStatusMailbox = Controller->V2.NextStatusMailbox;
+  while (NextStatusMailbox->Fields.CommandIdentifier > 0)
+    {
+       DAC960_V2_CommandIdentifier_T CommandIdentifier =
+           NextStatusMailbox->Fields.CommandIdentifier;
+       DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1];
+       Command->V2.CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+       Command->V2.RequestSenseLength =
+           NextStatusMailbox->Fields.RequestSenseLength;
+       Command->V2.DataTransferResidue =
+           NextStatusMailbox->Fields.DataTransferResidue;
+       NextStatusMailbox->Words[0] = 0;
+       if (++NextStatusMailbox > Controller->V2.LastStatusMailbox)
+           NextStatusMailbox = Controller->V2.FirstStatusMailbox;
+       DAC960_V2_ProcessCompletedCommand(Command);
+    }
+  Controller->V2.NextStatusMailbox = NextStatusMailbox;
+  /*
+    Attempt to remove additional I/O Requests from the Controller's
+    I/O Request Queue and queue them to the Controller.
+  */
+  DAC960_ProcessRequest(Controller);
+  spin_unlock_irqrestore(&Controller->queue_lock, flags);
+  return IRQ_HANDLED;
+}
 
 /*
   DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series
@@ -6962,6 +7079,14 @@
 
 #endif /* DAC960_GAM_MINOR */
 
+static struct DAC960_privdata DAC960_GEM_privdata = {
+	.HardwareType =		DAC960_GEM_Controller,
+	.FirmwareType 	=	DAC960_V2_Controller,
+	.InterruptHandler =	DAC960_GEM_InterruptHandler,
+	.MemoryWindowSize =	DAC960_GEM_RegisterWindowSize,
+};
+
+
 static struct DAC960_privdata DAC960_BA_privdata = {
 	.HardwareType =		DAC960_BA_Controller,
 	.FirmwareType 	=	DAC960_V2_Controller,
@@ -7007,6 +7132,13 @@
 static struct pci_device_id DAC960_id_table[] = {
 	{
 		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_GEM,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_GEM_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
 		.device		= PCI_DEVICE_ID_MYLEX_DAC960_BA,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index d5e8e71..a82f37f 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -2114,7 +2114,8 @@
   DAC960_LA_Controller =			3,	/* DAC1164P */
   DAC960_PG_Controller =			4,	/* DAC960PTL/PJ/PG */
   DAC960_PD_Controller =			5,	/* DAC960PU/PD/PL/P */
-  DAC960_P_Controller =				6	/* DAC960PU/PD/PL/P */
+  DAC960_P_Controller =				6,	/* DAC960PU/PD/PL/P */
+  DAC960_GEM_Controller =			7,	/* AcceleRAID 4/5/600 */
 }
 DAC960_HardwareType_T;
 
@@ -2541,6 +2542,320 @@
 }
 
 /*
+  Define the DAC960 GEM Series Controller Interface Register Offsets.
+ */
+
+#define DAC960_GEM_RegisterWindowSize	0x600
+
+typedef enum
+{
+  DAC960_GEM_InboundDoorBellRegisterReadSetOffset   =   0x214,
+  DAC960_GEM_InboundDoorBellRegisterClearOffset     =   0x218,
+  DAC960_GEM_OutboundDoorBellRegisterReadSetOffset  =   0x224,
+  DAC960_GEM_OutboundDoorBellRegisterClearOffset    =   0x228,
+  DAC960_GEM_InterruptStatusRegisterOffset          =   0x208,
+  DAC960_GEM_InterruptMaskRegisterReadSetOffset     =   0x22C,
+  DAC960_GEM_InterruptMaskRegisterClearOffset       =   0x230,
+  DAC960_GEM_CommandMailboxBusAddressOffset         =   0x510,
+  DAC960_GEM_CommandStatusOffset                    =   0x518,
+  DAC960_GEM_ErrorStatusRegisterReadSetOffset       =   0x224,
+  DAC960_GEM_ErrorStatusRegisterClearOffset         =   0x228,
+}
+DAC960_GEM_RegisterOffsets_T;
+
+/*
+  Define the structure of the DAC960 GEM Series Inbound Door Bell
+ */
+
+typedef union DAC960_GEM_InboundDoorBellRegister
+{
+  unsigned int All;
+  struct {
+    unsigned int :24;
+    boolean HardwareMailboxNewCommand:1;
+    boolean AcknowledgeHardwareMailboxStatus:1;
+    boolean GenerateInterrupt:1;
+    boolean ControllerReset:1;
+    boolean MemoryMailboxNewCommand:1;
+    unsigned int :3;
+  } Write;
+  struct {
+    unsigned int :24;
+    boolean HardwareMailboxFull:1;
+    boolean InitializationInProgress:1;
+    unsigned int :6;
+  } Read;
+}
+DAC960_GEM_InboundDoorBellRegister_T;
+
+/*
+  Define the structure of the DAC960 GEM Series Outbound Door Bell Register.
+ */
+typedef union DAC960_GEM_OutboundDoorBellRegister
+{
+  unsigned int All;
+  struct {
+    unsigned int :24;
+    boolean AcknowledgeHardwareMailboxInterrupt:1;
+    boolean AcknowledgeMemoryMailboxInterrupt:1;
+    unsigned int :6;
+  } Write;
+  struct {
+    unsigned int :24;
+    boolean HardwareMailboxStatusAvailable:1;
+    boolean MemoryMailboxStatusAvailable:1;
+    unsigned int :6;
+  } Read;
+}
+DAC960_GEM_OutboundDoorBellRegister_T;
+
+/*
+  Define the structure of the DAC960 GEM Series Interrupt Mask Register.
+ */
+typedef union DAC960_GEM_InterruptMaskRegister
+{
+  unsigned int All;
+  struct {
+    unsigned int :16;
+    unsigned int :8;
+    unsigned int HardwareMailboxInterrupt:1;
+    unsigned int MemoryMailboxInterrupt:1;
+    unsigned int :6;
+  } Bits;
+}
+DAC960_GEM_InterruptMaskRegister_T;
+
+/*
+  Define the structure of the DAC960 GEM Series Error Status Register.
+ */
+
+typedef union DAC960_GEM_ErrorStatusRegister
+{
+  unsigned int All;
+  struct {
+    unsigned int :24;
+    unsigned int :5;
+    boolean ErrorStatusPending:1;
+    unsigned int :2;
+  } Bits;
+}
+DAC960_GEM_ErrorStatusRegister_T;
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 GEM Series Controller Interface Registers.
+*/
+
+static inline
+void DAC960_GEM_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InboundDoorBellRegisterReadSetOffset);
+}
+
+static inline
+void DAC960_GEM_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InboundDoorBellRegisterClearOffset);
+}
+
+static inline
+void DAC960_GEM_GenerateInterrupt(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InboundDoorBellRegisterReadSetOffset);
+}
+
+static inline
+void DAC960_GEM_ControllerReset(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InboundDoorBellRegisterReadSetOffset);
+}
+
+static inline
+void DAC960_GEM_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InboundDoorBellRegisterReadSetOffset);
+}
+
+static inline
+boolean DAC960_GEM_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress +
+          DAC960_GEM_InboundDoorBellRegisterReadSetOffset);
+  return InboundDoorBellRegister.Read.HardwareMailboxFull;
+}
+
+static inline
+boolean DAC960_GEM_InitializationInProgressP(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress +
+          DAC960_GEM_InboundDoorBellRegisterReadSetOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
+void DAC960_GEM_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_OutboundDoorBellRegisterClearOffset);
+}
+
+static inline
+void DAC960_GEM_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_OutboundDoorBellRegisterClearOffset);
+}
+
+static inline
+void DAC960_GEM_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_OutboundDoorBellRegisterClearOffset);
+}
+
+static inline
+boolean DAC960_GEM_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readl(ControllerBaseAddress +
+          DAC960_GEM_OutboundDoorBellRegisterReadSetOffset);
+  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_GEM_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readl(ControllerBaseAddress +
+          DAC960_GEM_OutboundDoorBellRegisterReadSetOffset);
+  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_GEM_EnableInterrupts(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.HardwareMailboxInterrupt = true;
+  InterruptMaskRegister.Bits.MemoryMailboxInterrupt = true;
+  writel(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InterruptMaskRegisterClearOffset);
+}
+
+static inline
+void DAC960_GEM_DisableInterrupts(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.HardwareMailboxInterrupt = true;
+  InterruptMaskRegister.Bits.MemoryMailboxInterrupt = true;
+  writel(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_GEM_InterruptMaskRegisterReadSetOffset);
+}
+
+static inline
+boolean DAC960_GEM_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
+{
+  DAC960_GEM_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All =
+    readl(ControllerBaseAddress +
+          DAC960_GEM_InterruptMaskRegisterReadSetOffset);
+  return !(InterruptMaskRegister.Bits.HardwareMailboxInterrupt ||
+           InterruptMaskRegister.Bits.MemoryMailboxInterrupt);
+}
+
+static inline
+void DAC960_GEM_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
+				     *MemoryCommandMailbox,
+				   DAC960_V2_CommandMailbox_T
+				     *CommandMailbox)
+{
+  memcpy(&MemoryCommandMailbox->Words[1], &CommandMailbox->Words[1],
+	 sizeof(DAC960_V2_CommandMailbox_T) - sizeof(unsigned int));
+  wmb();
+  MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
+}
+
+static inline
+void DAC960_GEM_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
+				    dma_addr_t CommandMailboxDMA)
+{
+	dma_addr_writeql(CommandMailboxDMA,
+		ControllerBaseAddress +
+		DAC960_GEM_CommandMailboxBusAddressOffset);
+}
+
+static inline DAC960_V2_CommandIdentifier_T
+DAC960_GEM_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_GEM_CommandStatusOffset);
+}
+
+static inline DAC960_V2_CommandStatus_T
+DAC960_GEM_ReadCommandStatus(void __iomem *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_GEM_CommandStatusOffset + 2);
+}
+
+static inline boolean
+DAC960_GEM_ReadErrorStatus(void __iomem *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_GEM_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readl(ControllerBaseAddress + DAC960_GEM_ErrorStatusRegisterReadSetOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_GEM_CommandMailboxBusAddressOffset + 0);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_GEM_CommandMailboxBusAddressOffset + 1);
+  writel(0x03000000, ControllerBaseAddress +
+         DAC960_GEM_ErrorStatusRegisterClearOffset);
+  return true;
+}
+
+/*
   Define the DAC960 BA Series Controller Interface Register Offsets.
 */
 
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index e830be1..b594768 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -6,7 +6,7 @@
 
 config BLK_DEV_FD
 	tristate "Normal floppy disk support"
-	depends on (!ARCH_S390 && !M68K && !IA64 && !UML) || Q40 || (SUN3X && BROKEN) || ARCH_RPC || ARCH_EBSA285
+	depends on (!ARCH_S390 && !M68K && !IA64 && !UML && !ARM) || Q40 || (SUN3X && BROKEN) || ARCH_RPC || ARCH_EBSA285
 	---help---
 	  If you want to use the floppy disk drive(s) of your PC under Linux,
 	  say Y. Information about this driver, especially important for IBM
@@ -105,7 +105,7 @@
 
 config BLK_DEV_XD
 	tristate "XT hard disk support"
-	depends on ISA
+	depends on ISA && ISA_DMA_API
 	help
 	  Very old 8 bit hard disk controllers used in the IBM XT computer
 	  will be supported if you say Y here.
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index aa8b547..721ba80 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "6"
+#define VERSION "10"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 4780f79..0e97fcb 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -37,6 +37,13 @@
 
 	return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name);
 }
+/* firmware version */
+static ssize_t aoedisk_show_fwver(struct gendisk * disk, char *page)
+{
+	struct aoedev *d = disk->private_data;
+
+	return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver);
+}
 
 static struct disk_attribute disk_attr_state = {
 	.attr = {.name = "state", .mode = S_IRUGO },
@@ -50,6 +57,10 @@
 	.attr = {.name = "netif", .mode = S_IRUGO },
 	.show = aoedisk_show_netif
 };
+static struct disk_attribute disk_attr_fwver = {
+	.attr = {.name = "firmware-version", .mode = S_IRUGO },
+	.show = aoedisk_show_fwver
+};
 
 static void
 aoedisk_add_sysfs(struct aoedev *d)
@@ -57,6 +68,7 @@
 	sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr);
 	sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr);
 	sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr);
+	sysfs_create_file(&d->gd->kobj, &disk_attr_fwver.attr);
 }
 void
 aoedisk_rm_sysfs(struct aoedev *d)
@@ -64,6 +76,7 @@
 	sysfs_remove_link(&d->gd->kobj, "state");
 	sysfs_remove_link(&d->gd->kobj, "mac");
 	sysfs_remove_link(&d->gd->kobj, "netif");
+	sysfs_remove_link(&d->gd->kobj, "firmware-version");
 }
 
 static int
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index ec16c64..6e231c5 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -109,25 +109,22 @@
 	spin_lock_irqsave(&devlist_lock, flags);
 
 	for (d=devlist; d; d=d->next)
-		if (d->sysminor == sysminor
-		|| memcmp(d->addr, addr, sizeof d->addr) == 0)
+		if (d->sysminor == sysminor)
 			break;
 
 	if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) {
 		spin_unlock_irqrestore(&devlist_lock, flags);
 		printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
 		return NULL;
-	}
+	} /* if newdev, (d->flags & DEVFL_UP) == 0 for below */
 
 	spin_unlock_irqrestore(&devlist_lock, flags);
 	spin_lock_irqsave(&d->lock, flags);
 
 	d->ifp = ifp;
-
-	if (d->sysminor != sysminor
-	|| (d->flags & DEVFL_UP) == 0) {
+	memcpy(d->addr, addr, sizeof d->addr);
+	if ((d->flags & DEVFL_UP) == 0) {
 		aoedev_downdev(d); /* flushes outstanding frames */
-		memcpy(d->addr, addr, sizeof d->addr);
 		d->sysminor = sysminor;
 		d->aoemajor = AOEMAJOR(sysminor);
 		d->aoeminor = AOEMINOR(sysminor);
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index bc92aac..9e6f51c 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -7,6 +7,7 @@
 #include <linux/hdreg.h>
 #include <linux/blkdev.h>
 #include <linux/netdevice.h>
+#include <linux/moduleparam.h>
 #include "aoe.h"
 
 #define NECODES 5
@@ -26,6 +27,19 @@
 };
 
 static char aoe_iflist[IFLISTSZ];
+module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600);
+MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=\"dev1 [dev2 ...]\"\n");
+
+#ifndef MODULE
+static int __init aoe_iflist_setup(char *str)
+{
+	strncpy(aoe_iflist, str, IFLISTSZ);
+	aoe_iflist[IFLISTSZ - 1] = '\0';
+	return 1;
+}
+
+__setup("aoe_iflist=", aoe_iflist_setup);
+#endif
 
 int
 is_aoe_netif(struct net_device *ifp)
@@ -36,7 +50,8 @@
 	if (aoe_iflist[0] == '\0')
 		return 1;
 
-	for (p = aoe_iflist; *p; p = q + strspn(q, WHITESPACE)) {
+	p = aoe_iflist + strspn(aoe_iflist, WHITESPACE);
+	for (; *p; p = q + strspn(q, WHITESPACE)) {
 		q = p + strcspn(p, WHITESPACE);
 		if (q != p)
 			len = q - p;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 42dfa28..f0c1084 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3345,7 +3345,7 @@
 			struct block_device *bdev = opened_bdev[cnt];
 			if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
 				continue;
-			__invalidate_device(bdev, 0);
+			__invalidate_device(bdev);
 		}
 		up(&open_lock);
 	} else {
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index ab4db71..8bbe01d 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 #include <linux/kobj_map.h>
+#include <linux/buffer_head.h>
 
 #define MAX_PROBE_HASH 255	/* random */
 
@@ -676,7 +677,8 @@
 	int res = 0;
 	struct block_device *bdev = bdget_disk(disk, index);
 	if (bdev) {
-		res = __invalidate_device(bdev, 1);
+		fsync_bdev(bdev);
+		res = __invalidate_device(bdev);
 		bdput(bdev);
 	}
 	return res;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index efdf044..9e268dd 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -78,6 +78,7 @@
 #define DBG_RX          0x0200
 #define DBG_TX          0x0400
 static unsigned int debugflags;
+static unsigned int nbds_max = 16;
 #endif /* NDEBUG */
 
 static struct nbd_device nbd_dev[MAX_NBD];
@@ -647,7 +648,13 @@
 		return -EIO;
 	}
 
-	for (i = 0; i < MAX_NBD; i++) {
+	if (nbds_max > MAX_NBD) {
+		printk(KERN_CRIT "nbd: cannot allocate more than %u nbds; %u requested.\n", MAX_NBD,
+				nbds_max);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nbds_max; i++) {
 		struct gendisk *disk = alloc_disk(1);
 		if (!disk)
 			goto out;
@@ -673,7 +680,7 @@
 	dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
 
 	devfs_mk_dir("nbd");
-	for (i = 0; i < MAX_NBD; i++) {
+	for (i = 0; i < nbds_max; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
 		nbd_dev[i].file = NULL;
 		nbd_dev[i].magic = LO_MAGIC;
@@ -706,8 +713,9 @@
 static void __exit nbd_cleanup(void)
 {
 	int i;
-	for (i = 0; i < MAX_NBD; i++) {
+	for (i = 0; i < nbds_max; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
+		nbd_dev[i].magic = 0;
 		if (disk) {
 			del_gendisk(disk);
 			blk_cleanup_queue(disk->queue);
@@ -725,6 +733,8 @@
 MODULE_DESCRIPTION("Network Block Device");
 MODULE_LICENSE("GPL");
 
+module_param(nbds_max, int, 0444);
+MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize.");
 #ifndef NDEBUG
 module_param(debugflags, int, 0644);
 MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c
index 888c477..b1730b6 100644
--- a/drivers/block/noop-iosched.c
+++ b/drivers/block/noop-iosched.c
@@ -13,34 +13,13 @@
 static int elevator_noop_merge(request_queue_t *q, struct request **req,
 			       struct bio *bio)
 {
-	struct list_head *entry = &q->queue_head;
-	struct request *__rq;
 	int ret;
 
-	if ((ret = elv_try_last_merge(q, bio))) {
+	ret = elv_try_last_merge(q, bio);
+	if (ret != ELEVATOR_NO_MERGE)
 		*req = q->last_merge;
-		return ret;
-	}
 
-	while ((entry = entry->prev) != &q->queue_head) {
-		__rq = list_entry_rq(entry);
-
-		if (__rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER))
-			break;
-		else if (__rq->flags & REQ_STARTED)
-			break;
-
-		if (!blk_fs_request(__rq))
-			continue;
-
-		if ((ret = elv_try_merge(__rq, bio))) {
-			*req = __rq;
-			q->last_merge = __rq;
-			return ret;
-		}
-	}
-
-	return ELEVATOR_NO_MERGE;
+	return ret;
 }
 
 static void elevator_noop_merge_requests(request_queue_t *q, struct request *req,
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 9deca49..beaa561 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -645,7 +645,7 @@
 		ret = cdrom_mrw_bgformat_susp(cdi, 0);
 	}
 
-	if (!ret)
+	if (!ret && cdi->media_written)
 		ret = cdrom_flush_cache(cdi);
 
 	return ret;
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index 647a71b..ac96de1 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -292,7 +292,7 @@
 
 /* The interrupt handler will wake this queue up when it gets an
    interrupts. */
-DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
+static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
 static int irq_flag = 0;
 
 static int curr_control_reg = 0;	/* Current value of the control register */
@@ -2947,7 +2947,7 @@
 	return cdrom_media_changed(&scd_info);
 }
 
-struct block_device_operations scd_bdops =
+static struct block_device_operations scd_bdops =
 {
 	.owner		= THIS_MODULE,
 	.open		= scd_block_open,
@@ -3216,7 +3216,7 @@
 }
 
 
-void __exit cdu31a_exit(void)
+static void __exit cdu31a_exit(void)
 {
 	del_gendisk(scd_gendisk);
 	put_disk(scd_gendisk);
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index ccde7ab..07bbd24 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -107,20 +107,20 @@
    The _direct_ size is the number of sectors we're allowed to skip
    directly (performing a read instead of requesting the new sector
    needed */
-const int REQUEST_SIZE = 800;	/* should be less then 255 * 4 */
-const int DIRECT_SIZE = 400;	/* should be less then REQUEST_SIZE */
+static const int REQUEST_SIZE = 800;	/* should be less then 255 * 4 */
+static const int DIRECT_SIZE = 400;	/* should be less then REQUEST_SIZE */
 
 enum drivemodes { TOC, DATA, RAW, COOKED };
 enum datamodes { MODE0, MODE1, MODE2 };
 enum resetmodes { SOFT, HARD };
 
-const int SINGLE = 0x01;	/* single speed drive (FX001S, LU) */
-const int DOUBLE = 0x02;	/* double speed drive (FX001D, ..? */
-const int DOOR = 0x04;		/* door locking capability */
-const int MULTI = 0x08;		/* multi session capability */
+static const int SINGLE = 0x01;		/* single speed drive (FX001S, LU) */
+static const int DOUBLE = 0x02;		/* double speed drive (FX001D, ..? */
+static const int DOOR = 0x04;		/* door locking capability */
+static const int MULTI = 0x08;		/* multi session capability */
 
-const unsigned char READ1X = 0xc0;
-const unsigned char READ2X = 0xc1;
+static const unsigned char READ1X = 0xc0;
+static const unsigned char READ2X = 0xc1;
 
 
 /* DECLARATIONS ****************************************************/
@@ -210,9 +210,7 @@
  	repeated here to show what's going on.  And to sense, if they're
 	changed elsewhere. */
 
-/* declared in blk.h */
-int mcdx_init(void);
-void do_mcdx_request(request_queue_t * q);
+static int mcdx_init(void);
 
 static int mcdx_block_open(struct inode *inode, struct file *file)
 {
@@ -569,7 +567,7 @@
 	}
 }
 
-void do_mcdx_request(request_queue_t * q)
+static void do_mcdx_request(request_queue_t * q)
 {
 	struct s_drive_stuff *stuffp;
 	struct request *req;
@@ -1028,7 +1026,7 @@
 	return 0;
 }
 
-void __exit mcdx_exit(void)
+static void __exit mcdx_exit(void)
 {
 	int i;
 
@@ -1075,7 +1073,7 @@
 
 /* Support functions ************************************************/
 
-int __init mcdx_init_drive(int drive)
+static int __init mcdx_init_drive(int drive)
 {
 	struct s_version version;
 	struct gendisk *disk;
@@ -1261,7 +1259,7 @@
 	return 0;
 }
 
-int __init mcdx_init(void)
+static int __init mcdx_init(void)
 {
 	int drive;
 	xwarn("Version 2.14(hs) \n");
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index fc2c433..452d346 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -5895,7 +5895,7 @@
 }
 /*==========================================================================*/
 #ifdef MODULE
-void sbpcd_exit(void)
+static void sbpcd_exit(void)
 {
 	int j;
 	
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 096a120..5ed6515 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -153,7 +153,7 @@
 
 config ESPSERIAL
 	tristate "Hayes ESP serial port support"
-	depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP && ISA_DMA_API
 	help
 	  This is a driver which supports Hayes ESP serial ports.  Both single
 	  port cards and multiport cards are supported.  Make sure to read
@@ -195,7 +195,7 @@
 
 config SYNCLINK
 	tristate "Microgate SyncLink card support"
-	depends on SERIAL_NONSTANDARD && PCI
+	depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API
 	help
 	  Provides support for the SyncLink ISA and PCI multiprotocol serial
 	  adapters. These adapters support asynchronous and HDLC bit
@@ -399,6 +399,20 @@
 	  controller communication from user space (you want this!),
 	  say Y.  Otherwise, say N.
 
+config SGI_TIOCX
+       bool "SGI TIO CX driver support"
+       depends on (IA64_SGI_SN2 || IA64_GENERIC)
+       help
+         If you have an SGI Altix and you have fpga devices attached
+         to your TIO, say Y here, otherwise say N.
+
+config SGI_MBCS
+       tristate "SGI FPGA Core Services driver support"
+       depends on SGI_TIOCX
+       help
+         If you have an SGI Altix with an attached SABrick
+         say Y or M here, otherwise say N.
+
 source "drivers/serial/Kconfig"
 
 config UNIX98_PTYS
@@ -968,7 +982,7 @@
 
 config HANGCHECK_TIMER
 	tristate "Hangcheck timer"
-	depends on X86_64 || X86
+	depends on X86_64 || X86 || IA64 || PPC64 || ARCH_S390
 	help
 	  The hangcheck-timer module detects when the system has gone
 	  out to lunch past a certain margin.  It can reboot the system
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 54ed76a..e3f5c32 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -42,11 +42,12 @@
 obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
 obj-$(CONFIG_HVC_CONSOLE)	+= hvc_console.o hvsi.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
-obj-$(CONFIG_SGI_SNSC)		+= snsc.o
+obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
 obj-$(CONFIG_MMTIMER)		+= mmtimer.o
 obj-$(CONFIG_VIOCONS) += viocons.o
 obj-$(CONFIG_VIOTAPE)		+= viotape.o
 obj-$(CONFIG_HVCS)		+= hvcs.o
+obj-$(CONFIG_SGI_MBCS)		+= mbcs.o
 
 obj-$(CONFIG_PRINTER) += lp.o
 obj-$(CONFIG_TIPAR) += tipar.o
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index c86a22c..0212feb 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -192,7 +192,7 @@
 	{4, 1024, 0, 3}
 };
 
-struct agp_bridge_driver ali_generic_bridge = {
+static struct agp_bridge_driver ali_generic_bridge = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= ali_generic_sizes,
 	.size_type		= U32_APER_SIZE,
@@ -215,7 +215,7 @@
 	.agp_destroy_page	= ali_destroy_page,
 };
 
-struct agp_bridge_driver ali_m1541_bridge = {
+static struct agp_bridge_driver ali_m1541_bridge = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= ali_generic_sizes,
 	.size_type		= U32_APER_SIZE,
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index f1ea87e..e62a3c2 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -358,7 +358,7 @@
 	{.mask = 1, .type = 0}
 };
 
-struct agp_bridge_driver amd_irongate_driver = {
+static struct agp_bridge_driver amd_irongate_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= amd_irongate_sizes,
 	.size_type		= LVL2_APER_SIZE,
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 905f062..399c042 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -243,7 +243,7 @@
 }
 
 
-struct agp_bridge_driver amd_8151_driver = {
+static struct agp_bridge_driver amd_8151_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= amd_8151_sizes,
 	.size_type		= U32_APER_SIZE,
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 757dde0..a65f882 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -393,7 +393,7 @@
 	return 0;
 }
 
-struct agp_bridge_driver ati_generic_bridge = {
+static struct agp_bridge_driver ati_generic_bridge = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= ati_generic_sizes,
 	.size_type		= LVL2_APER_SIZE,
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index c3442f3c..2f3dfb6 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -97,7 +97,7 @@
 EXPORT_SYMBOL(agp_backend_release);
 
 
-struct { int mem, agp; } maxes_table[] = {
+static struct { int mem, agp; } maxes_table[] = {
 	{0, 0},
 	{32, 4},
 	{64, 28},
@@ -322,7 +322,7 @@
 	return 0;
 }
 
-void __exit agp_exit(void)
+static void __exit agp_exit(void)
 {
 }
 
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 2a87cec..1383c31 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -303,7 +303,7 @@
 }
 
 
-struct agp_bridge_driver efficeon_driver = {
+static struct agp_bridge_driver efficeon_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= efficeon_generic_sizes,
 	.size_type		= LVL2_APER_SIZE,
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index f633623..3dfb664 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -235,7 +235,7 @@
 
 /* File private list routines */
 
-struct agp_file_private *agp_find_private(pid_t pid)
+static struct agp_file_private *agp_find_private(pid_t pid)
 {
 	struct agp_file_private *curr;
 
@@ -250,7 +250,7 @@
 	return NULL;
 }
 
-void agp_insert_file_private(struct agp_file_private * priv)
+static void agp_insert_file_private(struct agp_file_private * priv)
 {
 	struct agp_file_private *prev;
 
@@ -262,7 +262,7 @@
 	agp_fe.file_priv_list = priv;
 }
 
-void agp_remove_file_private(struct agp_file_private * priv)
+static void agp_remove_file_private(struct agp_file_private * priv)
 {
 	struct agp_file_private *next;
 	struct agp_file_private *prev;
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 4f7a3e8..80dafa3 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -288,7 +288,7 @@
 };
 
 
-struct agp_bridge_driver nvidia_driver = {
+static struct agp_bridge_driver nvidia_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= nvidia_generic_sizes,
 	.size_type		= U8_APER_SIZE,
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index cfccacb..ebc0555 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -119,7 +119,7 @@
 	{4, 1024, 0, 3}
 };
 
-struct agp_bridge_driver sis_driver = {
+static struct agp_bridge_driver sis_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes 	= sis_generic_sizes,
 	.size_type		= U8_APER_SIZE,
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index bb338d9..10c2330 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -409,7 +409,7 @@
 	agp_device_command(command, 0);
 }
 
-struct agp_bridge_driver sworks_driver = {
+static struct agp_bridge_driver sworks_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= serverworks_sizes,
 	.size_type		= LVL2_APER_SIZE,
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index e1451dd..c847df5 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -170,7 +170,7 @@
 }
 
 
-struct agp_bridge_driver via_agp3_driver = {
+static struct agp_bridge_driver via_agp3_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= agp3_generic_sizes,
 	.size_type		= U8_APER_SIZE,
@@ -193,7 +193,7 @@
 	.agp_destroy_page	= agp_generic_destroy_page,
 };
 
-struct agp_bridge_driver via_driver = {
+static struct agp_bridge_driver via_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= via_generic_sizes,
 	.size_type		= U8_APER_SIZE,
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index 903e4c3..a229915 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -52,7 +52,7 @@
 #define KERNEL
 #include <linux/types.h>
 #include <linux/fs.h>
-#include <linux/mm.h>		/* for verify_area */
+#include <linux/mm.h>
 #include <linux/errno.h>	/* for -EBUSY */
 #include <linux/ioport.h>	/* for request_region */
 #include <linux/delay.h>	/* for loops_per_jiffy */
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 83d6b37..78e650f 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -3,7 +3,7 @@
  *
  * Driver for a little io fencing timer.
  *
- * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ * Copyright (C) 2002, 2003 Oracle.  All rights reserved.
  *
  * Author: Joel Becker <joel.becker@oracle.com>
  *
@@ -44,11 +44,14 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/reboot.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
+#include <linux/sysrq.h>
 
 
-#define VERSION_STR "0.5.0"
+#define VERSION_STR "0.9.0"
 
 #define DEFAULT_IOFENCE_MARGIN 60	/* Default fudge factor, in seconds */
 #define DEFAULT_IOFENCE_TICK 180	/* Default timer timeout, in seconds */
@@ -56,18 +59,89 @@
 static int hangcheck_tick = DEFAULT_IOFENCE_TICK;
 static int hangcheck_margin = DEFAULT_IOFENCE_MARGIN;
 static int hangcheck_reboot;  /* Defaults to not reboot */
+static int hangcheck_dump_tasks;  /* Defaults to not dumping SysRQ T */
 
-/* Driver options */
+/* options - modular */
 module_param(hangcheck_tick, int, 0);
 MODULE_PARM_DESC(hangcheck_tick, "Timer delay.");
 module_param(hangcheck_margin, int, 0);
 MODULE_PARM_DESC(hangcheck_margin, "If the hangcheck timer has been delayed more than hangcheck_margin seconds, the driver will fire.");
 module_param(hangcheck_reboot, int, 0);
 MODULE_PARM_DESC(hangcheck_reboot, "If nonzero, the machine will reboot when the timer margin is exceeded.");
+module_param(hangcheck_dump_tasks, int, 0);
+MODULE_PARM_DESC(hangcheck_dump_tasks, "If nonzero, the machine will dump the system task state when the timer margin is exceeded.");
 
-MODULE_AUTHOR("Joel Becker");
+MODULE_AUTHOR("Oracle");
 MODULE_DESCRIPTION("Hangcheck-timer detects when the system has gone out to lunch past a certain margin.");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION_STR);
+
+/* options - nonmodular */
+#ifndef MODULE
+
+static int __init hangcheck_parse_tick(char *str)
+{
+	int par;
+	if (get_option(&str,&par))
+		hangcheck_tick = par;
+	return 1;
+}
+
+static int __init hangcheck_parse_margin(char *str)
+{
+	int par;
+	if (get_option(&str,&par))
+		hangcheck_margin = par;
+	return 1;
+}
+
+static int __init hangcheck_parse_reboot(char *str)
+{
+	int par;
+	if (get_option(&str,&par))
+		hangcheck_reboot = par;
+	return 1;
+}
+
+static int __init hangcheck_parse_dump_tasks(char *str)
+{
+	int par;
+	if (get_option(&str,&par))
+		hangcheck_dump_tasks = par;
+	return 1;
+}
+
+__setup("hcheck_tick", hangcheck_parse_tick);
+__setup("hcheck_margin", hangcheck_parse_margin);
+__setup("hcheck_reboot", hangcheck_parse_reboot);
+__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
+#endif /* not MODULE */
+
+#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
+# define HAVE_MONOTONIC
+# define TIMER_FREQ 1000000000ULL
+#elif defined(CONFIG_ARCH_S390)
+/* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */
+# define TIMER_FREQ 0xFA240000ULL
+#elif defined(CONFIG_IA64)
+# define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq)
+#elif defined(CONFIG_PPC64)
+# define TIMER_FREQ (HZ*loops_per_jiffy)
+#endif
+
+#ifdef HAVE_MONOTONIC
+extern unsigned long long monotonic_clock(void);
+#else
+static inline unsigned long long monotonic_clock(void)
+{
+# ifdef __s390__
+	/* returns the TOD.  see 4-38 Principles of Op of zSeries */
+	return get_clock();
+# else
+	return get_cycles();
+# endif  /* __s390__ */
+}
+#endif  /* HAVE_MONOTONIC */
 
 
 /* Last time scheduled */
@@ -78,7 +152,6 @@
 static struct timer_list hangcheck_ticktock =
 		TIMER_INITIALIZER(hangcheck_fire, 0, 0);
 
-extern unsigned long long monotonic_clock(void);
 
 static void hangcheck_fire(unsigned long data)
 {
@@ -92,6 +165,12 @@
 		tsc_diff = (cur_tsc + (~0ULL - hangcheck_tsc)); /* or something */
 
 	if (tsc_diff > hangcheck_tsc_margin) {
+		if (hangcheck_dump_tasks) {
+			printk(KERN_CRIT "Hangcheck: Task state:\n");
+#ifdef CONFIG_MAGIC_SYSRQ
+			handle_sysrq('t', NULL, NULL);
+#endif  /* CONFIG_MAGIC_SYSRQ */
+		}
 		if (hangcheck_reboot) {
 			printk(KERN_CRIT "Hangcheck: hangcheck is restarting the machine.\n");
 			machine_restart(NULL);
@@ -108,10 +187,16 @@
 {
 	printk("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
 	       VERSION_STR, hangcheck_tick, hangcheck_margin);
-
-	hangcheck_tsc_margin = hangcheck_margin + hangcheck_tick;
-	hangcheck_tsc_margin *= 1000000000;
-
+#if defined (HAVE_MONOTONIC)
+	printk("Hangcheck: Using monotonic_clock().\n");
+#elif defined(__s390__)
+	printk("Hangcheck: Using TOD.\n");
+#else
+	printk("Hangcheck: Using get_cycles().\n");
+#endif  /* HAVE_MONOTONIC */
+	hangcheck_tsc_margin =
+		(unsigned long long)(hangcheck_margin + hangcheck_tick);
+	hangcheck_tsc_margin *= (unsigned long long)TIMER_FREQ;
 
 	hangcheck_tsc = monotonic_clock();
 	mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
@@ -123,6 +208,7 @@
 static void __exit hangcheck_exit(void)
 {
 	del_timer_sync(&hangcheck_ticktock);
+        printk("Hangcheck: Stopped hangcheck timer.\n");
 }
 
 module_init(hangcheck_init);
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 225b330..5ce9c62 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -235,7 +235,6 @@
 	if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
 	BT_CONTROL(BT_CLR_WR_PTR);
 	BT_CONTROL(BT_SMS_ATN);
-	BT_INTMASK_W(BT_BMC_HWRST);
 #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
 	if (BT_STATUS & BT_B2H_ATN) {
 		int i;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a6606a1..d7fb452 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2588,28 +2588,20 @@
 	deliver_response(msg);
 }
 
-static void
-send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
-		   struct ipmi_smi_msg *smi_msg,
-		   unsigned char seq, long seqid)
+static struct ipmi_smi_msg *
+smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
+		  unsigned char seq, long seqid)
 {
-	if (!smi_msg)
-		smi_msg = ipmi_alloc_smi_msg();
+	struct ipmi_smi_msg *smi_msg = ipmi_alloc_smi_msg();
 	if (!smi_msg)
 		/* If we can't allocate the message, then just return, we
 		   get 4 retries, so this should be ok. */
-		return;
+		return NULL;
 
 	memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
 	smi_msg->data_size = recv_msg->msg.data_len;
 	smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
 		
-	/* Send the new message.  We send with a zero priority.  It
-	   timed out, I doubt time is that critical now, and high
-	   priority messages are really only for messages to the local
-	   MC, which don't get resent. */
-	intf->handlers->sender(intf->send_info, smi_msg, 0);
-
 #ifdef DEBUG_MSGING
 	{
 		int m;
@@ -2619,6 +2611,7 @@
 		printk("\n");
 	}
 #endif
+	return smi_msg;
 }
 
 static void
@@ -2683,14 +2676,13 @@
 					intf->timed_out_ipmb_commands++;
 				spin_unlock(&intf->counter_lock);
 			} else {
+				struct ipmi_smi_msg *smi_msg;
 				/* More retries, send again. */
 
 				/* Start with the max timer, set to normal
 				   timer after the message is sent. */
 				ent->timeout = MAX_MSG_TIMEOUT;
 				ent->retries_left--;
-				send_from_recv_msg(intf, ent->recv_msg, NULL,
-						   j, ent->seqid);
 				spin_lock(&intf->counter_lock);
 				if (ent->recv_msg->addr.addr_type
 				    == IPMI_LAN_ADDR_TYPE)
@@ -2698,6 +2690,20 @@
 				else
 					intf->retransmitted_ipmb_commands++;
 				spin_unlock(&intf->counter_lock);
+				smi_msg = smi_from_recv_msg(intf,
+						ent->recv_msg, j, ent->seqid);
+				if(!smi_msg)
+					continue;
+
+				spin_unlock_irqrestore(&(intf->seq_lock),flags);
+				/* Send the new message.  We send with a zero
+				 * priority.  It timed out, I doubt time is
+				 * that critical now, and high priority
+				 * messages are really only for messages to the
+				 * local MC, which don't get resent. */
+				intf->handlers->sender(intf->send_info,
+							smi_msg, 0);
+				spin_lock_irqsave(&(intf->seq_lock), flags);
 			}
 		}
 		spin_unlock_irqrestore(&(intf->seq_lock), flags);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 29de259..298574e 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -100,6 +100,11 @@
 	/* FIXME - add watchdog stuff. */
 };
 
+/* Some BT-specific defines we need here. */
+#define IPMI_BT_INTMASK_REG		2
+#define IPMI_BT_INTMASK_CLEAR_IRQ_BIT	2
+#define IPMI_BT_INTMASK_ENABLE_IRQ_BIT	1
+
 enum si_type {
     SI_KCS, SI_SMIC, SI_BT
 };
@@ -875,6 +880,17 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs)
+{
+	struct smi_info *smi_info = data;
+	/* We need to clear the IRQ flag for the BT interface. */
+	smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG,
+			     IPMI_BT_INTMASK_CLEAR_IRQ_BIT
+			     | IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
+	return si_irq_handler(irq, data, regs);
+}
+
+
 static struct ipmi_smi_handlers handlers =
 {
 	.owner                  = THIS_MODULE,
@@ -1001,11 +1017,22 @@
 	if (!info->irq)
 		return 0;
 
-	rv = request_irq(info->irq,
-			 si_irq_handler,
-			 SA_INTERRUPT,
-			 DEVICE_NAME,
-			 info);
+	if (info->si_type == SI_BT) {
+		rv = request_irq(info->irq,
+				 si_bt_irq_handler,
+				 SA_INTERRUPT,
+				 DEVICE_NAME,
+				 info);
+		if (!rv)
+			/* Enable the interrupt in the BT interface. */
+			info->io.outputb(&info->io, IPMI_BT_INTMASK_REG,
+					 IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
+	} else
+		rv = request_irq(info->irq,
+				 si_irq_handler,
+				 SA_INTERRUPT,
+				 DEVICE_NAME,
+				 info);
 	if (rv) {
 		printk(KERN_WARNING
 		       "ipmi_si: %s unable to claim interrupt %d,"
@@ -1024,6 +1051,9 @@
 	if (!info->irq)
 		return;
 
+	if (info->si_type == SI_BT)
+		/* Disable the interrupt in the BT interface. */
+		info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0);
 	free_irq(info->irq, info);
 }
 
@@ -1526,8 +1556,17 @@
 		info->irq_setup = NULL;
 	}
 
-	regspacings[intf_num] = spmi->addr.register_bit_width / 8;
-	info->io.regspacing = spmi->addr.register_bit_width / 8;
+	if (spmi->addr.register_bit_width) {
+		/* A (hopefully) properly formed register bit width. */
+		regspacings[intf_num] = spmi->addr.register_bit_width / 8;
+		info->io.regspacing = spmi->addr.register_bit_width / 8;
+	} else {
+		/* Some broken systems get this wrong and set the value
+		 * to zero.  Assume it is the default spacing.  If that
+		 * is wrong, too bad, the vendor should fix the tables. */
+		regspacings[intf_num] = DEFAULT_REGSPACING;
+		info->io.regspacing = DEFAULT_REGSPACING;
+	}
 	regsizes[intf_num] = regspacings[intf_num];
 	info->io.regsize = regsizes[intf_num];
 	regshifts[intf_num] = spmi->addr.register_bit_offset;
@@ -1578,15 +1617,15 @@
 	u16	handle;
 } dmi_header_t;
 
-static int decode_dmi(dmi_header_t *dm, int intf_num)
+static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
 {
-	u8		*data = (u8 *)dm;
+	u8		__iomem *data = (u8 __iomem *)dm;
 	unsigned long  	base_addr;
 	u8		reg_spacing;
-	u8              len = dm->length;
+	u8              len = readb(&dm->length);
 	dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
 
-	ipmi_data->type = data[4];
+	ipmi_data->type = readb(&data[4]);
 
 	memcpy(&base_addr, data+8, sizeof(unsigned long));
 	if (len >= 0x11) {
@@ -1601,12 +1640,12 @@
 		}
 		/* If bit 4 of byte 0x10 is set, then the lsb for the address
 		   is odd. */
-		ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+		ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4);
 
-		ipmi_data->irq = data[0x11];
+		ipmi_data->irq = readb(&data[0x11]);
 
 		/* The top two bits of byte 0x10 hold the register spacing. */
-		reg_spacing = (data[0x10] & 0xC0) >> 6;
+		reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
 		switch(reg_spacing){
 		case 0x00: /* Byte boundaries */
 		    ipmi_data->offset = 1;
@@ -1623,12 +1662,18 @@
 		}
 	} else {
 		/* Old DMI spec. */
-		ipmi_data->base_addr = base_addr;
+		/* Note that technically, the lower bit of the base
+		 * address should be 1 if the address is I/O and 0 if
+		 * the address is in memory.  So many systems get that
+		 * wrong (and all that I have seen are I/O) so we just
+		 * ignore that bit and assume I/O.  Systems that use
+		 * memory should use the newer spec, anyway. */
+		ipmi_data->base_addr = base_addr & 0xfffe;
 		ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
 		ipmi_data->offset = 1;
 	}
 
-	ipmi_data->slave_addr = data[6];
+	ipmi_data->slave_addr = readb(&data[6]);
 
 	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
 		dmi_data_entries++;
@@ -1642,9 +1687,9 @@
 
 static int dmi_table(u32 base, int len, int num)
 {
-	u8 		  *buf;
-	struct dmi_header *dm;
-	u8 		  *data;
+	u8 		  __iomem *buf;
+	struct dmi_header __iomem *dm;
+	u8 		  __iomem *data;
 	int 		  i=1;
 	int		  status=-1;
 	int               intf_num = 0;
@@ -1657,12 +1702,12 @@
 
 	while(i<num && (data - buf) < len)
 	{
-		dm=(dmi_header_t *)data;
+		dm=(dmi_header_t __iomem *)data;
 
-		if((data-buf+dm->length) >= len)
+		if((data-buf+readb(&dm->length)) >= len)
         		break;
 
-		if (dm->type == 38) {
+		if (readb(&dm->type) == 38) {
 			if (decode_dmi(dm, intf_num) == 0) {
 				intf_num++;
 				if (intf_num >= SI_MAX_DRIVERS)
@@ -1670,8 +1715,8 @@
 			}
 		}
 
-	        data+=dm->length;
-		while((data-buf) < len && (*data || data[1]))
+	        data+=readb(&dm->length);
+		while((data-buf) < len && (readb(data)||readb(data+1)))
 			data++;
 		data+=2;
 		i++;
@@ -2199,7 +2244,7 @@
 	/* Wait until we know that we are out of any interrupt
 	   handlers might have been running before we freed the
 	   interrupt. */
-	synchronize_kernel();
+	synchronize_sched();
 
 	if (new_smi->si_sm) {
 		if (new_smi->handlers)
@@ -2312,7 +2357,7 @@
 	/* Wait until we know that we are out of any interrupt
 	   handlers might have been running before we freed the
 	   interrupt. */
-	synchronize_kernel();
+	synchronize_sched();
 
 	/* Wait for the timer to stop.  This avoids problems with race
 	   conditions removing the timer here. */
diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
index a0212b0..62791dd 100644
--- a/drivers/char/ipmi/ipmi_si_sm.h
+++ b/drivers/char/ipmi/ipmi_si_sm.h
@@ -51,7 +51,7 @@
 	/* Generic info used by the actual handling routines, the
            state machine shouldn't touch these. */
 	void *info;
-	void *addr;
+	void __iomem *addr;
 	int  regspacing;
 	int  regsize;
 	int  regshift;
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index fd70938..fcd1c02 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -709,11 +709,11 @@
 		if (expect_close == 42) {
 			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
 			ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
-			clear_bit(0, &ipmi_wdog_open);
 		} else {
 			printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
 			ipmi_heartbeat();
 		}
+		clear_bit(0, &ipmi_wdog_open);
 	}
 
 	ipmi_fasync (-1, filep, 0);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 3ce51c6..7b19e02 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1026,7 +1026,8 @@
 		put_queue(vc, data);
 }
 
-void kbd_keycode(unsigned int keycode, int down, int hw_raw, struct pt_regs *regs)
+static void kbd_keycode(unsigned int keycode, int down,
+			int hw_raw, struct pt_regs *regs)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned short keysym, *key_map;
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
new file mode 100644
index 0000000..ac9cfa9
--- /dev/null
+++ b/drivers/char/mbcs.c
@@ -0,0 +1,849 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+/*
+ *	MOATB Core Services driver.
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/uio.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/tiocx.h>
+#include "mbcs.h"
+
+#define MBCS_DEBUG 0
+#if MBCS_DEBUG
+#define DBG(fmt...)    printk(KERN_ALERT fmt)
+#else
+#define DBG(fmt...)
+#endif
+int mbcs_major;
+
+LIST_HEAD(soft_list);
+
+/*
+ * file operations
+ */
+struct file_operations mbcs_ops = {
+	.open = mbcs_open,
+	.llseek = mbcs_sram_llseek,
+	.read = mbcs_sram_read,
+	.write = mbcs_sram_write,
+	.mmap = mbcs_gscr_mmap,
+};
+
+struct mbcs_callback_arg {
+	int minor;
+	struct cx_dev *cx_dev;
+};
+
+static inline void mbcs_getdma_init(struct getdma *gdma)
+{
+	memset(gdma, 0, sizeof(struct getdma));
+	gdma->DoneIntEnable = 1;
+}
+
+static inline void mbcs_putdma_init(struct putdma *pdma)
+{
+	memset(pdma, 0, sizeof(struct putdma));
+	pdma->DoneIntEnable = 1;
+}
+
+static inline void mbcs_algo_init(struct algoblock *algo_soft)
+{
+	memset(algo_soft, 0, sizeof(struct algoblock));
+}
+
+static inline void mbcs_getdma_set(void *mmr,
+		       uint64_t hostAddr,
+		       uint64_t localAddr,
+		       uint64_t localRamSel,
+		       uint64_t numPkts,
+		       uint64_t amoEnable,
+		       uint64_t intrEnable,
+		       uint64_t peerIO,
+		       uint64_t amoHostDest,
+		       uint64_t amoModType, uint64_t intrHostDest,
+		       uint64_t intrVector)
+{
+	union dma_control rdma_control;
+	union dma_amo_dest amo_dest;
+	union intr_dest intr_dest;
+	union dma_localaddr local_addr;
+	union dma_hostaddr host_addr;
+
+	rdma_control.dma_control_reg = 0;
+	amo_dest.dma_amo_dest_reg = 0;
+	intr_dest.intr_dest_reg = 0;
+	local_addr.dma_localaddr_reg = 0;
+	host_addr.dma_hostaddr_reg = 0;
+
+	host_addr.dma_sys_addr = hostAddr;
+	MBCS_MMR_SET(mmr, MBCS_RD_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);
+
+	local_addr.dma_ram_addr = localAddr;
+	local_addr.dma_ram_sel = localRamSel;
+	MBCS_MMR_SET(mmr, MBCS_RD_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);
+
+	rdma_control.dma_op_length = numPkts;
+	rdma_control.done_amo_en = amoEnable;
+	rdma_control.done_int_en = intrEnable;
+	rdma_control.pio_mem_n = peerIO;
+	MBCS_MMR_SET(mmr, MBCS_RD_DMA_CTRL, rdma_control.dma_control_reg);
+
+	amo_dest.dma_amo_sys_addr = amoHostDest;
+	amo_dest.dma_amo_mod_type = amoModType;
+	MBCS_MMR_SET(mmr, MBCS_RD_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);
+
+	intr_dest.address = intrHostDest;
+	intr_dest.int_vector = intrVector;
+	MBCS_MMR_SET(mmr, MBCS_RD_DMA_INT_DEST, intr_dest.intr_dest_reg);
+
+}
+
+static inline void mbcs_putdma_set(void *mmr,
+		       uint64_t hostAddr,
+		       uint64_t localAddr,
+		       uint64_t localRamSel,
+		       uint64_t numPkts,
+		       uint64_t amoEnable,
+		       uint64_t intrEnable,
+		       uint64_t peerIO,
+		       uint64_t amoHostDest,
+		       uint64_t amoModType,
+		       uint64_t intrHostDest, uint64_t intrVector)
+{
+	union dma_control wdma_control;
+	union dma_amo_dest amo_dest;
+	union intr_dest intr_dest;
+	union dma_localaddr local_addr;
+	union dma_hostaddr host_addr;
+
+	wdma_control.dma_control_reg = 0;
+	amo_dest.dma_amo_dest_reg = 0;
+	intr_dest.intr_dest_reg = 0;
+	local_addr.dma_localaddr_reg = 0;
+	host_addr.dma_hostaddr_reg = 0;
+
+	host_addr.dma_sys_addr = hostAddr;
+	MBCS_MMR_SET(mmr, MBCS_WR_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);
+
+	local_addr.dma_ram_addr = localAddr;
+	local_addr.dma_ram_sel = localRamSel;
+	MBCS_MMR_SET(mmr, MBCS_WR_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);
+
+	wdma_control.dma_op_length = numPkts;
+	wdma_control.done_amo_en = amoEnable;
+	wdma_control.done_int_en = intrEnable;
+	wdma_control.pio_mem_n = peerIO;
+	MBCS_MMR_SET(mmr, MBCS_WR_DMA_CTRL, wdma_control.dma_control_reg);
+
+	amo_dest.dma_amo_sys_addr = amoHostDest;
+	amo_dest.dma_amo_mod_type = amoModType;
+	MBCS_MMR_SET(mmr, MBCS_WR_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);
+
+	intr_dest.address = intrHostDest;
+	intr_dest.int_vector = intrVector;
+	MBCS_MMR_SET(mmr, MBCS_WR_DMA_INT_DEST, intr_dest.intr_dest_reg);
+
+}
+
+static inline void mbcs_algo_set(void *mmr,
+		     uint64_t amoHostDest,
+		     uint64_t amoModType,
+		     uint64_t intrHostDest,
+		     uint64_t intrVector, uint64_t algoStepCount)
+{
+	union dma_amo_dest amo_dest;
+	union intr_dest intr_dest;
+	union algo_step step;
+
+	step.algo_step_reg = 0;
+	intr_dest.intr_dest_reg = 0;
+	amo_dest.dma_amo_dest_reg = 0;
+
+	amo_dest.dma_amo_sys_addr = amoHostDest;
+	amo_dest.dma_amo_mod_type = amoModType;
+	MBCS_MMR_SET(mmr, MBCS_ALG_AMO_DEST, amo_dest.dma_amo_dest_reg);
+
+	intr_dest.address = intrHostDest;
+	intr_dest.int_vector = intrVector;
+	MBCS_MMR_SET(mmr, MBCS_ALG_INT_DEST, intr_dest.intr_dest_reg);
+
+	step.alg_step_cnt = algoStepCount;
+	MBCS_MMR_SET(mmr, MBCS_ALG_STEP, step.algo_step_reg);
+}
+
+static inline int mbcs_getdma_start(struct mbcs_soft *soft)
+{
+	void *mmr_base;
+	struct getdma *gdma;
+	uint64_t numPkts;
+	union cm_control cm_control;
+
+	mmr_base = soft->mmr_base;
+	gdma = &soft->getdma;
+
+	/* check that host address got setup */
+	if (!gdma->hostAddr)
+		return -1;
+
+	numPkts =
+	    (gdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;
+
+	/* program engine */
+	mbcs_getdma_set(mmr_base, tiocx_dma_addr(gdma->hostAddr),
+		   gdma->localAddr,
+		   (gdma->localAddr < MB2) ? 0 :
+		   (gdma->localAddr < MB4) ? 1 :
+		   (gdma->localAddr < MB6) ? 2 : 3,
+		   numPkts,
+		   gdma->DoneAmoEnable,
+		   gdma->DoneIntEnable,
+		   gdma->peerIO,
+		   gdma->amoHostDest,
+		   gdma->amoModType,
+		   gdma->intrHostDest, gdma->intrVector);
+
+	/* start engine */
+	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+	cm_control.rd_dma_go = 1;
+	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
+
+	return 0;
+
+}
+
+static inline int mbcs_putdma_start(struct mbcs_soft *soft)
+{
+	void *mmr_base;
+	struct putdma *pdma;
+	uint64_t numPkts;
+	union cm_control cm_control;
+
+	mmr_base = soft->mmr_base;
+	pdma = &soft->putdma;
+
+	/* check that host address got setup */
+	if (!pdma->hostAddr)
+		return -1;
+
+	numPkts =
+	    (pdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;
+
+	/* program engine */
+	mbcs_putdma_set(mmr_base, tiocx_dma_addr(pdma->hostAddr),
+		   pdma->localAddr,
+		   (pdma->localAddr < MB2) ? 0 :
+		   (pdma->localAddr < MB4) ? 1 :
+		   (pdma->localAddr < MB6) ? 2 : 3,
+		   numPkts,
+		   pdma->DoneAmoEnable,
+		   pdma->DoneIntEnable,
+		   pdma->peerIO,
+		   pdma->amoHostDest,
+		   pdma->amoModType,
+		   pdma->intrHostDest, pdma->intrVector);
+
+	/* start engine */
+	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+	cm_control.wr_dma_go = 1;
+	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
+
+	return 0;
+
+}
+
+static inline int mbcs_algo_start(struct mbcs_soft *soft)
+{
+	struct algoblock *algo_soft = &soft->algo;
+	void *mmr_base = soft->mmr_base;
+	union cm_control cm_control;
+
+	if (down_interruptible(&soft->algolock))
+		return -ERESTARTSYS;
+
+	atomic_set(&soft->algo_done, 0);
+
+	mbcs_algo_set(mmr_base,
+		 algo_soft->amoHostDest,
+		 algo_soft->amoModType,
+		 algo_soft->intrHostDest,
+		 algo_soft->intrVector, algo_soft->algoStepCount);
+
+	/* start algorithm */
+	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+	cm_control.alg_done_int_en = 1;
+	cm_control.alg_go = 1;
+	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
+
+	up(&soft->algolock);
+
+	return 0;
+}
+
+static inline ssize_t
+do_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr,
+		      size_t len, loff_t * off)
+{
+	int rv = 0;
+
+	if (down_interruptible(&soft->dmawritelock))
+		return -ERESTARTSYS;
+
+	atomic_set(&soft->dmawrite_done, 0);
+
+	soft->putdma.hostAddr = hostAddr;
+	soft->putdma.localAddr = *off;
+	soft->putdma.bytes = len;
+
+	if (mbcs_putdma_start(soft) < 0) {
+		DBG(KERN_ALERT "do_mbcs_sram_dmawrite: "
+					"mbcs_putdma_start failed\n");
+		rv = -EAGAIN;
+		goto dmawrite_exit;
+	}
+
+	if (wait_event_interruptible(soft->dmawrite_queue,
+					atomic_read(&soft->dmawrite_done))) {
+		rv = -ERESTARTSYS;
+		goto dmawrite_exit;
+	}
+
+	rv = len;
+	*off += len;
+
+dmawrite_exit:
+	up(&soft->dmawritelock);
+
+	return rv;
+}
+
+static inline ssize_t
+do_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr,
+		     size_t len, loff_t * off)
+{
+	int rv = 0;
+
+	if (down_interruptible(&soft->dmareadlock))
+		return -ERESTARTSYS;
+
+	atomic_set(&soft->dmawrite_done, 0);
+
+	soft->getdma.hostAddr = hostAddr;
+	soft->getdma.localAddr = *off;
+	soft->getdma.bytes = len;
+
+	if (mbcs_getdma_start(soft) < 0) {
+		DBG(KERN_ALERT "mbcs_strategy: mbcs_getdma_start failed\n");
+		rv = -EAGAIN;
+		goto dmaread_exit;
+	}
+
+	if (wait_event_interruptible(soft->dmaread_queue,
+					atomic_read(&soft->dmaread_done))) {
+		rv = -ERESTARTSYS;
+		goto dmaread_exit;
+	}
+
+	rv = len;
+	*off += len;
+
+dmaread_exit:
+	up(&soft->dmareadlock);
+
+	return rv;
+}
+
+int mbcs_open(struct inode *ip, struct file *fp)
+{
+	struct mbcs_soft *soft;
+	int minor;
+
+	minor = iminor(ip);
+
+	list_for_each_entry(soft, &soft_list, list) {
+		if (soft->nasid == minor) {
+			fp->private_data = soft->cxdev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off)
+{
+	struct cx_dev *cx_dev = fp->private_data;
+	struct mbcs_soft *soft = cx_dev->soft;
+	uint64_t hostAddr;
+	int rv = 0;
+
+	hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));
+	if (hostAddr == 0)
+		return -ENOMEM;
+
+	rv = do_mbcs_sram_dmawrite(soft, hostAddr, len, off);
+	if (rv < 0)
+		goto exit;
+
+	if (copy_to_user(buf, (void *)hostAddr, len))
+		rv = -EFAULT;
+
+      exit:
+	free_pages(hostAddr, get_order(len));
+
+	return rv;
+}
+
+ssize_t
+mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off)
+{
+	struct cx_dev *cx_dev = fp->private_data;
+	struct mbcs_soft *soft = cx_dev->soft;
+	uint64_t hostAddr;
+	int rv = 0;
+
+	hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));
+	if (hostAddr == 0)
+		return -ENOMEM;
+
+	if (copy_from_user((void *)hostAddr, buf, len)) {
+		rv = -EFAULT;
+		goto exit;
+	}
+
+	rv = do_mbcs_sram_dmaread(soft, hostAddr, len, off);
+
+      exit:
+	free_pages(hostAddr, get_order(len));
+
+	return rv;
+}
+
+loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
+{
+	loff_t newpos;
+
+	switch (whence) {
+	case 0:		/* SEEK_SET */
+		newpos = off;
+		break;
+
+	case 1:		/* SEEK_CUR */
+		newpos = filp->f_pos + off;
+		break;
+
+	case 2:		/* SEEK_END */
+		newpos = MBCS_SRAM_SIZE + off;
+		break;
+
+	default:		/* can't happen */
+		return -EINVAL;
+	}
+
+	if (newpos < 0)
+		return -EINVAL;
+
+	filp->f_pos = newpos;
+
+	return newpos;
+}
+
+static uint64_t mbcs_pioaddr(struct mbcs_soft *soft, uint64_t offset)
+{
+	uint64_t mmr_base;
+
+	mmr_base = (uint64_t) (soft->mmr_base + offset);
+
+	return mmr_base;
+}
+
+static void mbcs_debug_pioaddr_set(struct mbcs_soft *soft)
+{
+	soft->debug_addr = mbcs_pioaddr(soft, MBCS_DEBUG_START);
+}
+
+static void mbcs_gscr_pioaddr_set(struct mbcs_soft *soft)
+{
+	soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START);
+}
+
+int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+	struct cx_dev *cx_dev = fp->private_data;
+	struct mbcs_soft *soft = cx_dev->soft;
+
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
+	if (remap_pfn_range(vma,
+			    vma->vm_start,
+			    __pa(soft->gscr_addr) >> PAGE_SHIFT,
+			    PAGE_SIZE,
+			    vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
+
+/**
+ * mbcs_completion_intr_handler - Primary completion handler.
+ * @irq: irq
+ * @arg: soft struct for device
+ * @ep: regs
+ *
+ */
+static irqreturn_t
+mbcs_completion_intr_handler(int irq, void *arg, struct pt_regs *ep)
+{
+	struct mbcs_soft *soft = (struct mbcs_soft *)arg;
+	void *mmr_base;
+	union cm_status cm_status;
+	union cm_control cm_control;
+
+	mmr_base = soft->mmr_base;
+	cm_status.cm_status_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_STATUS);
+
+	if (cm_status.rd_dma_done) {
+		/* stop dma-read engine, clear status */
+		cm_control.cm_control_reg =
+		    MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+		cm_control.rd_dma_clr = 1;
+		MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
+			     cm_control.cm_control_reg);
+		atomic_set(&soft->dmaread_done, 1);
+		wake_up(&soft->dmaread_queue);
+	}
+	if (cm_status.wr_dma_done) {
+		/* stop dma-write engine, clear status */
+		cm_control.cm_control_reg =
+		    MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+		cm_control.wr_dma_clr = 1;
+		MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
+			     cm_control.cm_control_reg);
+		atomic_set(&soft->dmawrite_done, 1);
+		wake_up(&soft->dmawrite_queue);
+	}
+	if (cm_status.alg_done) {
+		/* clear status */
+		cm_control.cm_control_reg =
+		    MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+		cm_control.alg_done_clr = 1;
+		MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
+			     cm_control.cm_control_reg);
+		atomic_set(&soft->algo_done, 1);
+		wake_up(&soft->algo_queue);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * mbcs_intr_alloc - Allocate interrupts.
+ * @dev: device pointer
+ *
+ */
+static int mbcs_intr_alloc(struct cx_dev *dev)
+{
+	struct sn_irq_info *sn_irq;
+	struct mbcs_soft *soft;
+	struct getdma *getdma;
+	struct putdma *putdma;
+	struct algoblock *algo;
+
+	soft = dev->soft;
+	getdma = &soft->getdma;
+	putdma = &soft->putdma;
+	algo = &soft->algo;
+
+	soft->get_sn_irq = NULL;
+	soft->put_sn_irq = NULL;
+	soft->algo_sn_irq = NULL;
+
+	sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
+	if (sn_irq == NULL)
+		return -EAGAIN;
+	soft->get_sn_irq = sn_irq;
+	getdma->intrHostDest = sn_irq->irq_xtalkaddr;
+	getdma->intrVector = sn_irq->irq_irq;
+	if (request_irq(sn_irq->irq_irq,
+			(void *)mbcs_completion_intr_handler, SA_SHIRQ,
+			"MBCS get intr", (void *)soft)) {
+		tiocx_irq_free(soft->get_sn_irq);
+		return -EAGAIN;
+	}
+
+	sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
+	if (sn_irq == NULL) {
+		free_irq(soft->get_sn_irq->irq_irq, soft);
+		tiocx_irq_free(soft->get_sn_irq);
+		return -EAGAIN;
+	}
+	soft->put_sn_irq = sn_irq;
+	putdma->intrHostDest = sn_irq->irq_xtalkaddr;
+	putdma->intrVector = sn_irq->irq_irq;
+	if (request_irq(sn_irq->irq_irq,
+			(void *)mbcs_completion_intr_handler, SA_SHIRQ,
+			"MBCS put intr", (void *)soft)) {
+		tiocx_irq_free(soft->put_sn_irq);
+		free_irq(soft->get_sn_irq->irq_irq, soft);
+		tiocx_irq_free(soft->get_sn_irq);
+		return -EAGAIN;
+	}
+
+	sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
+	if (sn_irq == NULL) {
+		free_irq(soft->put_sn_irq->irq_irq, soft);
+		tiocx_irq_free(soft->put_sn_irq);
+		free_irq(soft->get_sn_irq->irq_irq, soft);
+		tiocx_irq_free(soft->get_sn_irq);
+		return -EAGAIN;
+	}
+	soft->algo_sn_irq = sn_irq;
+	algo->intrHostDest = sn_irq->irq_xtalkaddr;
+	algo->intrVector = sn_irq->irq_irq;
+	if (request_irq(sn_irq->irq_irq,
+			(void *)mbcs_completion_intr_handler, SA_SHIRQ,
+			"MBCS algo intr", (void *)soft)) {
+		tiocx_irq_free(soft->algo_sn_irq);
+		free_irq(soft->put_sn_irq->irq_irq, soft);
+		tiocx_irq_free(soft->put_sn_irq);
+		free_irq(soft->get_sn_irq->irq_irq, soft);
+		tiocx_irq_free(soft->get_sn_irq);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+/**
+ * mbcs_intr_dealloc - Remove interrupts.
+ * @dev: device pointer
+ *
+ */
+static void mbcs_intr_dealloc(struct cx_dev *dev)
+{
+	struct mbcs_soft *soft;
+
+	soft = dev->soft;
+
+	free_irq(soft->get_sn_irq->irq_irq, soft);
+	tiocx_irq_free(soft->get_sn_irq);
+	free_irq(soft->put_sn_irq->irq_irq, soft);
+	tiocx_irq_free(soft->put_sn_irq);
+	free_irq(soft->algo_sn_irq->irq_irq, soft);
+	tiocx_irq_free(soft->algo_sn_irq);
+}
+
+static inline int mbcs_hw_init(struct mbcs_soft *soft)
+{
+	void *mmr_base = soft->mmr_base;
+	union cm_control cm_control;
+	union cm_req_timeout cm_req_timeout;
+	uint64_t err_stat;
+
+	cm_req_timeout.cm_req_timeout_reg =
+	    MBCS_MMR_GET(mmr_base, MBCS_CM_REQ_TOUT);
+
+	cm_req_timeout.time_out = MBCS_CM_CONTROL_REQ_TOUT_MASK;
+	MBCS_MMR_SET(mmr_base, MBCS_CM_REQ_TOUT,
+		     cm_req_timeout.cm_req_timeout_reg);
+
+	mbcs_gscr_pioaddr_set(soft);
+	mbcs_debug_pioaddr_set(soft);
+
+	/* clear errors */
+	err_stat = MBCS_MMR_GET(mmr_base, MBCS_CM_ERR_STAT);
+	MBCS_MMR_SET(mmr_base, MBCS_CM_CLR_ERR_STAT, err_stat);
+	MBCS_MMR_ZERO(mmr_base, MBCS_CM_ERROR_DETAIL1);
+
+	/* enable interrupts */
+	/* turn off 2^23 (INT_EN_PIO_REQ_ADDR_INV) */
+	MBCS_MMR_SET(mmr_base, MBCS_CM_ERR_INT_EN, 0x3ffffff7e00ffUL);
+
+	/* arm status regs and clear engines */
+	cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
+	cm_control.rearm_stat_regs = 1;
+	cm_control.alg_clr = 1;
+	cm_control.wr_dma_clr = 1;
+	cm_control.rd_dma_clr = 1;
+
+	MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
+
+	return 0;
+}
+
+static ssize_t show_algo(struct device *dev, char *buf)
+{
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+	struct mbcs_soft *soft = cx_dev->soft;
+	uint64_t debug0;
+
+	/*
+	 * By convention, the first debug register contains the
+	 * algorithm number and revision.
+	 */
+	debug0 = *(uint64_t *) soft->debug_addr;
+
+	return sprintf(buf, "0x%lx 0x%lx\n",
+		       (debug0 >> 32), (debug0 & 0xffffffff));
+}
+
+static ssize_t store_algo(struct device *dev, const char *buf, size_t count)
+{
+	int n;
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+	struct mbcs_soft *soft = cx_dev->soft;
+
+	if (count <= 0)
+		return 0;
+
+	n = simple_strtoul(buf, NULL, 0);
+
+	if (n == 1) {
+		mbcs_algo_start(soft);
+		if (wait_event_interruptible(soft->algo_queue,
+					atomic_read(&soft->algo_done)))
+			return -ERESTARTSYS;
+	}
+
+	return count;
+}
+
+DEVICE_ATTR(algo, 0644, show_algo, store_algo);
+
+/**
+ * mbcs_probe - Initialize for device
+ * @dev: device pointer
+ * @device_id: id table pointer
+ *
+ */
+static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id)
+{
+	struct mbcs_soft *soft;
+
+	dev->soft = NULL;
+
+	soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL);
+	if (soft == NULL)
+		return -ENOMEM;
+
+	soft->nasid = dev->cx_id.nasid;
+	list_add(&soft->list, &soft_list);
+	soft->mmr_base = (void *)tiocx_swin_base(dev->cx_id.nasid);
+	dev->soft = soft;
+	soft->cxdev = dev;
+
+	init_waitqueue_head(&soft->dmawrite_queue);
+	init_waitqueue_head(&soft->dmaread_queue);
+	init_waitqueue_head(&soft->algo_queue);
+
+	init_MUTEX(&soft->dmawritelock);
+	init_MUTEX(&soft->dmareadlock);
+	init_MUTEX(&soft->algolock);
+
+	mbcs_getdma_init(&soft->getdma);
+	mbcs_putdma_init(&soft->putdma);
+	mbcs_algo_init(&soft->algo);
+
+	mbcs_hw_init(soft);
+
+	/* Allocate interrupts */
+	mbcs_intr_alloc(dev);
+
+	device_create_file(&dev->dev, &dev_attr_algo);
+
+	return 0;
+}
+
+static int mbcs_remove(struct cx_dev *dev)
+{
+	if (dev->soft) {
+		mbcs_intr_dealloc(dev);
+		kfree(dev->soft);
+	}
+
+	device_remove_file(&dev->dev, &dev_attr_algo);
+
+	return 0;
+}
+
+const struct cx_device_id __devinitdata mbcs_id_table[] = {
+	{
+	 .part_num = MBCS_PART_NUM,
+	 .mfg_num = MBCS_MFG_NUM,
+	 },
+	{
+	 .part_num = MBCS_PART_NUM_ALG0,
+	 .mfg_num = MBCS_MFG_NUM,
+	 },
+	{0, 0}
+};
+
+MODULE_DEVICE_TABLE(cx, mbcs_id_table);
+
+struct cx_drv mbcs_driver = {
+	.name = DEVICE_NAME,
+	.id_table = mbcs_id_table,
+	.probe = mbcs_probe,
+	.remove = mbcs_remove,
+};
+
+static void __exit mbcs_exit(void)
+{
+	int rv;
+
+	rv = unregister_chrdev(mbcs_major, DEVICE_NAME);
+	if (rv < 0)
+		DBG(KERN_ALERT "Error in unregister_chrdev: %d\n", rv);
+
+	cx_driver_unregister(&mbcs_driver);
+}
+
+static int __init mbcs_init(void)
+{
+	int rv;
+
+	// Put driver into chrdevs[].  Get major number.
+	rv = register_chrdev(mbcs_major, DEVICE_NAME, &mbcs_ops);
+	if (rv < 0) {
+		DBG(KERN_ALERT "mbcs_init: can't get major number. %d\n", rv);
+		return rv;
+	}
+	mbcs_major = rv;
+
+	return cx_driver_register(&mbcs_driver);
+}
+
+module_init(mbcs_init);
+module_exit(mbcs_exit);
+
+MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
+MODULE_DESCRIPTION("Driver for MOATB Core Services");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h
new file mode 100644
index 0000000..e7fd47e
--- /dev/null
+++ b/drivers/char/mbcs.h
@@ -0,0 +1,553 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#ifndef __MBCS_H__
+#define __MBCS_H__
+
+/*
+ * General macros
+ */
+#define MB	(1024*1024)
+#define MB2	(2*MB)
+#define MB4	(4*MB)
+#define MB6	(6*MB)
+
+/*
+ * Offsets and masks
+ */
+#define MBCS_CM_ID		0x0000	/* Identification */
+#define MBCS_CM_STATUS		0x0008	/* Status */
+#define MBCS_CM_ERROR_DETAIL1	0x0010	/* Error Detail1 */
+#define MBCS_CM_ERROR_DETAIL2	0x0018	/* Error Detail2 */
+#define MBCS_CM_CONTROL		0x0020	/* Control */
+#define MBCS_CM_REQ_TOUT	0x0028	/* Request Time-out */
+#define MBCS_CM_ERR_INT_DEST	0x0038	/* Error Interrupt Destination */
+#define MBCS_CM_TARG_FL		0x0050	/* Target Flush */
+#define MBCS_CM_ERR_STAT	0x0060	/* Error Status */
+#define MBCS_CM_CLR_ERR_STAT	0x0068	/* Clear Error Status */
+#define MBCS_CM_ERR_INT_EN	0x0070	/* Error Interrupt Enable */
+#define MBCS_RD_DMA_SYS_ADDR	0x0100	/* Read DMA System Address */
+#define MBCS_RD_DMA_LOC_ADDR	0x0108	/* Read DMA Local Address */
+#define MBCS_RD_DMA_CTRL	0x0110	/* Read DMA Control */
+#define MBCS_RD_DMA_AMO_DEST	0x0118	/* Read DMA AMO Destination */
+#define MBCS_RD_DMA_INT_DEST	0x0120	/* Read DMA Interrupt Destination */
+#define MBCS_RD_DMA_AUX_STAT	0x0130	/* Read DMA Auxillary Status */
+#define MBCS_WR_DMA_SYS_ADDR	0x0200	/* Write DMA System Address */
+#define MBCS_WR_DMA_LOC_ADDR	0x0208	/* Write DMA Local Address */
+#define MBCS_WR_DMA_CTRL	0x0210	/* Write DMA Control */
+#define MBCS_WR_DMA_AMO_DEST	0x0218	/* Write DMA AMO Destination */
+#define MBCS_WR_DMA_INT_DEST	0x0220	/* Write DMA Interrupt Destination */
+#define MBCS_WR_DMA_AUX_STAT	0x0230	/* Write DMA Auxillary Status */
+#define MBCS_ALG_AMO_DEST	0x0300	/* Algorithm AMO Destination */
+#define MBCS_ALG_INT_DEST	0x0308	/* Algorithm Interrupt Destination */
+#define MBCS_ALG_OFFSETS	0x0310
+#define MBCS_ALG_STEP		0x0318	/* Algorithm Step */
+
+#define MBCS_GSCR_START		0x0000000
+#define MBCS_DEBUG_START	0x0100000
+#define MBCS_RAM0_START		0x0200000
+#define MBCS_RAM1_START		0x0400000
+#define MBCS_RAM2_START		0x0600000
+
+#define MBCS_CM_CONTROL_REQ_TOUT_MASK 0x0000000000ffffffUL
+//#define PIO_BASE_ADDR_BASE_OFFSET_MASK 0x00fffffffff00000UL
+
+#define MBCS_SRAM_SIZE		(1024*1024)
+#define MBCS_CACHELINE_SIZE	128
+
+/*
+ * MMR get's and put's
+ */
+#define MBCS_MMR_ADDR(mmr_base, offset)((uint64_t *)(mmr_base + offset))
+#define MBCS_MMR_SET(mmr_base, offset, value) {			\
+	uint64_t *mbcs_mmr_set_u64p, readback;				\
+	mbcs_mmr_set_u64p = (uint64_t *)(mmr_base + offset);	\
+	*mbcs_mmr_set_u64p = value;					\
+	readback = *mbcs_mmr_set_u64p; \
+}
+#define MBCS_MMR_GET(mmr_base, offset) *(uint64_t *)(mmr_base + offset)
+#define MBCS_MMR_ZERO(mmr_base, offset) MBCS_MMR_SET(mmr_base, offset, 0)
+
+/*
+ * MBCS mmr structures
+ */
+union cm_id {
+	uint64_t cm_id_reg;
+	struct {
+		uint64_t always_one:1,	// 0
+		 mfg_id:11,	// 11:1
+		 part_num:16,	// 27:12
+		 bitstream_rev:8,	// 35:28
+		:28;		// 63:36
+	};
+};
+
+union cm_status {
+	uint64_t cm_status_reg;
+	struct {
+		uint64_t pending_reads:8,	// 7:0
+		 pending_writes:8,	// 15:8
+		 ice_rsp_credits:8,	// 23:16
+		 ice_req_credits:8,	// 31:24
+		 cm_req_credits:8,	// 39:32
+		:1,		// 40
+		 rd_dma_in_progress:1,	// 41
+		 rd_dma_done:1,	// 42
+		:1,		// 43
+		 wr_dma_in_progress:1,	// 44
+		 wr_dma_done:1,	// 45
+		 alg_waiting:1,	// 46
+		 alg_pipe_running:1,	// 47
+		 alg_done:1,	// 48
+		:3,		// 51:49
+		 pending_int_reqs:8,	// 59:52
+		:3,		// 62:60
+		 alg_half_speed_sel:1;	// 63
+	};
+};
+
+union cm_error_detail1 {
+	uint64_t cm_error_detail1_reg;
+	struct {
+		uint64_t packet_type:4,	// 3:0
+		 source_id:2,	// 5:4
+		 data_size:2,	// 7:6
+		 tnum:8,	// 15:8
+		 byte_enable:8,	// 23:16
+		 gfx_cred:8,	// 31:24
+		 read_type:2,	// 33:32
+		 pio_or_memory:1,	// 34
+		 head_cw_error:1,	// 35
+		:12,		// 47:36
+		 head_error_bit:1,	// 48
+		 data_error_bit:1,	// 49
+		:13,		// 62:50
+		 valid:1;	// 63
+	};
+};
+
+union cm_error_detail2 {
+	uint64_t cm_error_detail2_reg;
+	struct {
+		uint64_t address:56,	// 55:0
+		:8;		// 63:56
+	};
+};
+
+union cm_control {
+	uint64_t cm_control_reg;
+	struct {
+		uint64_t cm_id:2,	// 1:0
+		:2,		// 3:2
+		 max_trans:5,	// 8:4
+		:3,		// 11:9
+		 address_mode:1,	// 12
+		:7,		// 19:13
+		 credit_limit:8,	// 27:20
+		:5,		// 32:28
+		 rearm_stat_regs:1,	// 33
+		 prescalar_byp:1,	// 34
+		 force_gap_war:1,	// 35
+		 rd_dma_go:1,	// 36
+		 wr_dma_go:1,	// 37
+		 alg_go:1,	// 38
+		 rd_dma_clr:1,	// 39
+		 wr_dma_clr:1,	// 40
+		 alg_clr:1,	// 41
+		:2,		// 43:42
+		 alg_wait_step:1,	// 44
+		 alg_done_amo_en:1,	// 45
+		 alg_done_int_en:1,	// 46
+		:1,		// 47
+		 alg_sram0_locked:1,	// 48
+		 alg_sram1_locked:1,	// 49
+		 alg_sram2_locked:1,	// 50
+		 alg_done_clr:1,	// 51
+		:12;		// 63:52
+	};
+};
+
+union cm_req_timeout {
+	uint64_t cm_req_timeout_reg;
+	struct {
+		uint64_t time_out:24,	// 23:0
+		:40;		// 63:24
+	};
+};
+
+union intr_dest {
+	uint64_t intr_dest_reg;
+	struct {
+		uint64_t address:56,	// 55:0
+		 int_vector:8;	// 63:56
+	};
+};
+
+union cm_error_status {
+	uint64_t cm_error_status_reg;
+	struct {
+		uint64_t ecc_sbe:1,	// 0
+		 ecc_mbe:1,	// 1
+		 unsupported_req:1,	// 2
+		 unexpected_rsp:1,	// 3
+		 bad_length:1,	// 4
+		 bad_datavalid:1,	// 5
+		 buffer_overflow:1,	// 6
+		 request_timeout:1,	// 7
+		:8,		// 15:8
+		 head_inv_data_size:1,	// 16
+		 rsp_pactype_inv:1,	// 17
+		 head_sb_err:1,	// 18
+		 missing_head:1,	// 19
+		 head_inv_rd_type:1,	// 20
+		 head_cmd_err_bit:1,	// 21
+		 req_addr_align_inv:1,	// 22
+		 pio_req_addr_inv:1,	// 23
+		 req_range_dsize_inv:1,	// 24
+		 early_term:1,	// 25
+		 early_tail:1,	// 26
+		 missing_tail:1,	// 27
+		 data_flit_sb_err:1,	// 28
+		 cm2hcm_req_cred_of:1,	// 29
+		 cm2hcm_rsp_cred_of:1,	// 30
+		 rx_bad_didn:1,	// 31
+		 rd_dma_err_rsp:1,	// 32
+		 rd_dma_tnum_tout:1,	// 33
+		 rd_dma_multi_tnum_tou:1,	// 34
+		 wr_dma_err_rsp:1,	// 35
+		 wr_dma_tnum_tout:1,	// 36
+		 wr_dma_multi_tnum_tou:1,	// 37
+		 alg_data_overflow:1,	// 38
+		 alg_data_underflow:1,	// 39
+		 ram0_access_conflict:1,	// 40
+		 ram1_access_conflict:1,	// 41
+		 ram2_access_conflict:1,	// 42
+		 ram0_perr:1,	// 43
+		 ram1_perr:1,	// 44
+		 ram2_perr:1,	// 45
+		 int_gen_rsp_err:1,	// 46
+		 int_gen_tnum_tout:1,	// 47
+		 rd_dma_prog_err:1,	// 48
+		 wr_dma_prog_err:1,	// 49
+		:14;		// 63:50
+	};
+};
+
+union cm_clr_error_status {
+	uint64_t cm_clr_error_status_reg;
+	struct {
+		uint64_t clr_ecc_sbe:1,	// 0
+		 clr_ecc_mbe:1,	// 1
+		 clr_unsupported_req:1,	// 2
+		 clr_unexpected_rsp:1,	// 3
+		 clr_bad_length:1,	// 4
+		 clr_bad_datavalid:1,	// 5
+		 clr_buffer_overflow:1,	// 6
+		 clr_request_timeout:1,	// 7
+		:8,		// 15:8
+		 clr_head_inv_data_siz:1,	// 16
+		 clr_rsp_pactype_inv:1,	// 17
+		 clr_head_sb_err:1,	// 18
+		 clr_missing_head:1,	// 19
+		 clr_head_inv_rd_type:1,	// 20
+		 clr_head_cmd_err_bit:1,	// 21
+		 clr_req_addr_align_in:1,	// 22
+		 clr_pio_req_addr_inv:1,	// 23
+		 clr_req_range_dsize_i:1,	// 24
+		 clr_early_term:1,	// 25
+		 clr_early_tail:1,	// 26
+		 clr_missing_tail:1,	// 27
+		 clr_data_flit_sb_err:1,	// 28
+		 clr_cm2hcm_req_cred_o:1,	// 29
+		 clr_cm2hcm_rsp_cred_o:1,	// 30
+		 clr_rx_bad_didn:1,	// 31
+		 clr_rd_dma_err_rsp:1,	// 32
+		 clr_rd_dma_tnum_tout:1,	// 33
+		 clr_rd_dma_multi_tnum:1,	// 34
+		 clr_wr_dma_err_rsp:1,	// 35
+		 clr_wr_dma_tnum_tout:1,	// 36
+		 clr_wr_dma_multi_tnum:1,	// 37
+		 clr_alg_data_overflow:1,	// 38
+		 clr_alg_data_underflo:1,	// 39
+		 clr_ram0_access_confl:1,	// 40
+		 clr_ram1_access_confl:1,	// 41
+		 clr_ram2_access_confl:1,	// 42
+		 clr_ram0_perr:1,	// 43
+		 clr_ram1_perr:1,	// 44
+		 clr_ram2_perr:1,	// 45
+		 clr_int_gen_rsp_err:1,	// 46
+		 clr_int_gen_tnum_tout:1,	// 47
+		 clr_rd_dma_prog_err:1,	// 48
+		 clr_wr_dma_prog_err:1,	// 49
+		:14;		// 63:50
+	};
+};
+
+union cm_error_intr_enable {
+	uint64_t cm_error_intr_enable_reg;
+	struct {
+		uint64_t int_en_ecc_sbe:1,	// 0
+		 int_en_ecc_mbe:1,	// 1
+		 int_en_unsupported_re:1,	// 2
+		 int_en_unexpected_rsp:1,	// 3
+		 int_en_bad_length:1,	// 4
+		 int_en_bad_datavalid:1,	// 5
+		 int_en_buffer_overflo:1,	// 6
+		 int_en_request_timeou:1,	// 7
+		:8,		// 15:8
+		 int_en_head_inv_data_:1,	// 16
+		 int_en_rsp_pactype_in:1,	// 17
+		 int_en_head_sb_err:1,	// 18
+		 int_en_missing_head:1,	// 19
+		 int_en_head_inv_rd_ty:1,	// 20
+		 int_en_head_cmd_err_b:1,	// 21
+		 int_en_req_addr_align:1,	// 22
+		 int_en_pio_req_addr_i:1,	// 23
+		 int_en_req_range_dsiz:1,	// 24
+		 int_en_early_term:1,	// 25
+		 int_en_early_tail:1,	// 26
+		 int_en_missing_tail:1,	// 27
+		 int_en_data_flit_sb_e:1,	// 28
+		 int_en_cm2hcm_req_cre:1,	// 29
+		 int_en_cm2hcm_rsp_cre:1,	// 30
+		 int_en_rx_bad_didn:1,	// 31
+		 int_en_rd_dma_err_rsp:1,	// 32
+		 int_en_rd_dma_tnum_to:1,	// 33
+		 int_en_rd_dma_multi_t:1,	// 34
+		 int_en_wr_dma_err_rsp:1,	// 35
+		 int_en_wr_dma_tnum_to:1,	// 36
+		 int_en_wr_dma_multi_t:1,	// 37
+		 int_en_alg_data_overf:1,	// 38
+		 int_en_alg_data_under:1,	// 39
+		 int_en_ram0_access_co:1,	// 40
+		 int_en_ram1_access_co:1,	// 41
+		 int_en_ram2_access_co:1,	// 42
+		 int_en_ram0_perr:1,	// 43
+		 int_en_ram1_perr:1,	// 44
+		 int_en_ram2_perr:1,	// 45
+		 int_en_int_gen_rsp_er:1,	// 46
+		 int_en_int_gen_tnum_t:1,	// 47
+		 int_en_rd_dma_prog_er:1,	// 48
+		 int_en_wr_dma_prog_er:1,	// 49
+		:14;		// 63:50
+	};
+};
+
+struct cm_mmr {
+	union cm_id id;
+	union cm_status status;
+	union cm_error_detail1 err_detail1;
+	union cm_error_detail2 err_detail2;
+	union cm_control control;
+	union cm_req_timeout req_timeout;
+	uint64_t reserved1[1];
+	union intr_dest int_dest;
+	uint64_t reserved2[2];
+	uint64_t targ_flush;
+	uint64_t reserved3[1];
+	union cm_error_status err_status;
+	union cm_clr_error_status clr_err_status;
+	union cm_error_intr_enable int_enable;
+};
+
+union dma_hostaddr {
+	uint64_t dma_hostaddr_reg;
+	struct {
+		uint64_t dma_sys_addr:56,	// 55:0
+		:8;		// 63:56
+	};
+};
+
+union dma_localaddr {
+	uint64_t dma_localaddr_reg;
+	struct {
+		uint64_t dma_ram_addr:21,	// 20:0
+		 dma_ram_sel:2,	// 22:21
+		:41;		// 63:23
+	};
+};
+
+union dma_control {
+	uint64_t dma_control_reg;
+	struct {
+		uint64_t dma_op_length:16,	// 15:0
+		:18,		// 33:16
+		 done_amo_en:1,	// 34
+		 done_int_en:1,	// 35
+		:1,		// 36
+		 pio_mem_n:1,	// 37
+		:26;		// 63:38
+	};
+};
+
+union dma_amo_dest {
+	uint64_t dma_amo_dest_reg;
+	struct {
+		uint64_t dma_amo_sys_addr:56,	// 55:0
+		 dma_amo_mod_type:3,	// 58:56
+		:5;		// 63:59
+	};
+};
+
+union rdma_aux_status {
+	uint64_t rdma_aux_status_reg;
+	struct {
+		uint64_t op_num_pacs_left:17,	// 16:0
+		:5,		// 21:17
+		 lrsp_buff_empty:1,	// 22
+		:17,		// 39:23
+		 pending_reqs_left:6,	// 45:40
+		:18;		// 63:46
+	};
+};
+
+struct rdma_mmr {
+	union dma_hostaddr host_addr;
+	union dma_localaddr local_addr;
+	union dma_control control;
+	union dma_amo_dest amo_dest;
+	union intr_dest intr_dest;
+	union rdma_aux_status aux_status;
+};
+
+union wdma_aux_status {
+	uint64_t wdma_aux_status_reg;
+	struct {
+		uint64_t op_num_pacs_left:17,	// 16:0
+		:4,		// 20:17
+		 lreq_buff_empty:1,	// 21
+		:18,		// 39:22
+		 pending_reqs_left:6,	// 45:40
+		:18;		// 63:46
+	};
+};
+
+struct wdma_mmr {
+	union dma_hostaddr host_addr;
+	union dma_localaddr local_addr;
+	union dma_control control;
+	union dma_amo_dest amo_dest;
+	union intr_dest intr_dest;
+	union wdma_aux_status aux_status;
+};
+
+union algo_step {
+	uint64_t algo_step_reg;
+	struct {
+		uint64_t alg_step_cnt:16,	// 15:0
+		:48;		// 63:16
+	};
+};
+
+struct algo_mmr {
+	union dma_amo_dest amo_dest;
+	union intr_dest intr_dest;
+	union {
+		uint64_t algo_offset_reg;
+		struct {
+			uint64_t sram0_offset:7,	// 6:0
+			reserved0:1,	// 7
+			sram1_offset:7,	// 14:8
+			reserved1:1,	// 15
+			sram2_offset:7,	// 22:16
+			reserved2:14;	// 63:23
+		};
+	} sram_offset;
+	union algo_step step;
+};
+
+struct mbcs_mmr {
+	struct cm_mmr cm;
+	uint64_t reserved1[17];
+	struct rdma_mmr rdDma;
+	uint64_t reserved2[25];
+	struct wdma_mmr wrDma;
+	uint64_t reserved3[25];
+	struct algo_mmr algo;
+	uint64_t reserved4[156];
+};
+
+/*
+ * defines
+ */
+#define DEVICE_NAME "mbcs"
+#define MBCS_PART_NUM 0xfff0
+#define MBCS_PART_NUM_ALG0 0xf001
+#define MBCS_MFG_NUM  0x1
+
+struct algoblock {
+	uint64_t amoHostDest;
+	uint64_t amoModType;
+	uint64_t intrHostDest;
+	uint64_t intrVector;
+	uint64_t algoStepCount;
+};
+
+struct getdma {
+	uint64_t hostAddr;
+	uint64_t localAddr;
+	uint64_t bytes;
+	uint64_t DoneAmoEnable;
+	uint64_t DoneIntEnable;
+	uint64_t peerIO;
+	uint64_t amoHostDest;
+	uint64_t amoModType;
+	uint64_t intrHostDest;
+	uint64_t intrVector;
+};
+
+struct putdma {
+	uint64_t hostAddr;
+	uint64_t localAddr;
+	uint64_t bytes;
+	uint64_t DoneAmoEnable;
+	uint64_t DoneIntEnable;
+	uint64_t peerIO;
+	uint64_t amoHostDest;
+	uint64_t amoModType;
+	uint64_t intrHostDest;
+	uint64_t intrVector;
+};
+
+struct mbcs_soft {
+	struct list_head list;
+	struct cx_dev *cxdev;
+	int major;
+	int nasid;
+	void *mmr_base;
+	wait_queue_head_t dmawrite_queue;
+	wait_queue_head_t dmaread_queue;
+	wait_queue_head_t algo_queue;
+	struct sn_irq_info *get_sn_irq;
+	struct sn_irq_info *put_sn_irq;
+	struct sn_irq_info *algo_sn_irq;
+	struct getdma getdma;
+	struct putdma putdma;
+	struct algoblock algo;
+	uint64_t gscr_addr;	// pio addr
+	uint64_t ram0_addr;	// pio addr
+	uint64_t ram1_addr;	// pio addr
+	uint64_t ram2_addr;	// pio addr
+	uint64_t debug_addr;	// pio addr
+	atomic_t dmawrite_done;
+	atomic_t dmaread_done;
+	atomic_t algo_done;
+	struct semaphore dmawritelock;
+	struct semaphore dmareadlock;
+	struct semaphore algolock;
+};
+
+extern int mbcs_open(struct inode *ip, struct file *fp);
+extern ssize_t mbcs_sram_read(struct file *fp, char __user *buf, size_t len,
+			      loff_t * off);
+extern ssize_t mbcs_sram_write(struct file *fp, const char __user *buf, size_t len,
+			       loff_t * off);
+extern loff_t mbcs_sram_llseek(struct file *filp, loff_t off, int whence);
+extern int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma);
+
+#endif				// __MBCS_H__
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index a91ae27..763893e 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -221,7 +221,7 @@
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
    Some architectures may need more. -- Changed to LONG to
    support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
-long rio_irqmask = -1;
+static long rio_irqmask = -1;
 
 MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");
 MODULE_DESCRIPTION("RIO driver");
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index 8e61be3..ed867db 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -116,7 +116,7 @@
 
 /* Time read/write */
 
-static void s3c2410_rtc_gettime(struct rtc_time *rtc_tm)
+static int s3c2410_rtc_gettime(struct rtc_time *rtc_tm)
 {
 	unsigned int have_retried = 0;
 
@@ -151,6 +151,8 @@
 
 	rtc_tm->tm_year += 100;
 	rtc_tm->tm_mon -= 1;
+
+	return 0;
 }
 
 
@@ -171,7 +173,7 @@
 	return 0;
 }
 
-static void s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm)
+static int s3c2410_rtc_getalarm(struct rtc_wkalrm *alrm)
 {
 	struct rtc_time *alm_tm = &alrm->time;
 	unsigned int alm_en;
@@ -231,6 +233,8 @@
 	}
 
 	/* todo - set alrm->enabled ? */
+
+	return 0;
 }
 
 static int s3c2410_rtc_setalarm(struct rtc_wkalrm *alrm)
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index ffb9143..e3c0b52 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -374,6 +374,7 @@
 	void *salbuf;
 	struct class_simple *snsc_class;
 	dev_t first_dev, dev;
+	nasid_t event_nasid = ia64_sn_get_console_nasid();
 
 	if (alloc_chrdev_region(&first_dev, 0, numionodes,
 				SYSCTL_BASENAME) < 0) {
@@ -441,6 +442,13 @@
 			ia64_sn_irtr_intr_enable(scd->scd_nasid,
 						 0 /*ignored */ ,
 						 SAL_IROUTER_INTR_RECV);
+
+                        /* on the console nasid, prepare to receive
+                         * system controller environmental events
+                         */
+                        if(scd->scd_nasid == event_nasid) {
+                                scdrv_event_init(scd);
+                        }
 	}
 	return 0;
 }
diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
index c22c6c5..a9efc13 100644
--- a/drivers/char/snsc.h
+++ b/drivers/char/snsc.h
@@ -47,4 +47,44 @@
 	nasid_t scd_nasid;	/* Node on which subchannels are opened. */
 };
 
+
+/* argument types */
+#define IR_ARG_INT              0x00    /* 4-byte integer (big-endian)  */
+#define IR_ARG_ASCII            0x01    /* null-terminated ASCII string */
+#define IR_ARG_UNKNOWN          0x80    /* unknown data type.  The low
+                                         * 7 bits will contain the data
+                                         * length.                      */
+#define IR_ARG_UNKNOWN_LENGTH_MASK	0x7f
+
+
+/* system controller event codes */
+#define EV_CLASS_MASK		0xf000ul
+#define EV_SEVERITY_MASK	0x0f00ul
+#define EV_COMPONENT_MASK	0x00fful
+
+#define EV_CLASS_POWER		0x1000ul
+#define EV_CLASS_FAN		0x2000ul
+#define EV_CLASS_TEMP		0x3000ul
+#define EV_CLASS_ENV		0x4000ul
+#define EV_CLASS_TEST_FAULT	0x5000ul
+#define EV_CLASS_TEST_WARNING	0x6000ul
+#define EV_CLASS_PWRD_NOTIFY	0x8000ul
+
+#define EV_SEVERITY_POWER_STABLE	0x0000ul
+#define EV_SEVERITY_POWER_LOW_WARNING	0x0100ul
+#define EV_SEVERITY_POWER_HIGH_WARNING	0x0200ul
+#define EV_SEVERITY_POWER_HIGH_FAULT	0x0300ul
+#define EV_SEVERITY_POWER_LOW_FAULT	0x0400ul
+
+#define EV_SEVERITY_FAN_STABLE		0x0000ul
+#define EV_SEVERITY_FAN_WARNING		0x0100ul
+#define EV_SEVERITY_FAN_FAULT		0x0200ul
+
+#define EV_SEVERITY_TEMP_STABLE		0x0000ul
+#define EV_SEVERITY_TEMP_ADVISORY	0x0100ul
+#define EV_SEVERITY_TEMP_CRITICAL	0x0200ul
+#define EV_SEVERITY_TEMP_FAULT		0x0300ul
+
+void scdrv_event_init(struct sysctl_data_s *);
+
 #endif /* _SN_SYSCTL_H_ */
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
new file mode 100644
index 0000000..d692af5
--- /dev/null
+++ b/drivers/char/snsc_event.c
@@ -0,0 +1,304 @@
+/*
+ * SN Platform system controller communication support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * System controller event handler
+ *
+ * These routines deal with environmental events arriving from the
+ * system controllers.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/byteorder/generic.h>
+#include <asm/sn/sn_sal.h>
+#include "snsc.h"
+
+static struct subch_data_s *event_sd;
+
+void scdrv_event(unsigned long);
+DECLARE_TASKLET(sn_sysctl_event, scdrv_event, 0);
+
+/*
+ * scdrv_event_interrupt
+ *
+ * Pull incoming environmental events off the physical link to the
+ * system controller and put them in a temporary holding area in SAL.
+ * Schedule scdrv_event() to move them along to their ultimate
+ * destination.
+ */
+static irqreturn_t
+scdrv_event_interrupt(int irq, void *subch_data, struct pt_regs *regs)
+{
+	struct subch_data_s *sd = subch_data;
+	unsigned long flags;
+	int status;
+
+	spin_lock_irqsave(&sd->sd_rlock, flags);
+	status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
+
+	if ((status > 0) && (status & SAL_IROUTER_INTR_RECV)) {
+		tasklet_schedule(&sn_sysctl_event);
+	}
+	spin_unlock_irqrestore(&sd->sd_rlock, flags);
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * scdrv_parse_event
+ *
+ * Break an event (as read from SAL) into useful pieces so we can decide
+ * what to do with it.
+ */
+static int
+scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
+{
+	char *desc_end;
+
+	/* record event source address */
+	*src = be32_to_cpup((__be32 *)event);
+	event += 4; 			/* move on to event code */
+
+	/* record the system controller's event code */
+	*code = be32_to_cpup((__be32 *)event);
+	event += 4;			/* move on to event arguments */
+
+	/* how many arguments are in the packet? */
+	if (*event++ != 2) {
+		/* if not 2, give up */
+		return -1;
+	}
+
+	/* parse out the ESP code */
+	if (*event++ != IR_ARG_INT) {
+		/* not an integer argument, so give up */
+		return -1;
+	}
+	*esp_code = be32_to_cpup((__be32 *)event);
+	event += 4;
+
+	/* parse out the event description */
+	if (*event++ != IR_ARG_ASCII) {
+		/* not an ASCII string, so give up */
+		return -1;
+	}
+	event[CHUNKSIZE-1] = '\0';	/* ensure this string ends! */
+	event += 2; 			/* skip leading CR/LF */
+	desc_end = desc + sprintf(desc, "%s", event);
+
+	/* strip trailing CR/LF (if any) */
+	for (desc_end--;
+	     (desc_end != desc) && ((*desc_end == 0xd) || (*desc_end == 0xa));
+	     desc_end--) {
+		*desc_end = '\0';
+	}
+
+	return 0;
+}
+
+
+/*
+ * scdrv_event_severity
+ *
+ * Figure out how urgent a message we should write to the console/syslog
+ * via printk.
+ */
+static char *
+scdrv_event_severity(int code)
+{
+	int ev_class = (code & EV_CLASS_MASK);
+	int ev_severity = (code & EV_SEVERITY_MASK);
+	char *pk_severity = KERN_NOTICE;
+
+	switch (ev_class) {
+	case EV_CLASS_POWER:
+		switch (ev_severity) {
+		case EV_SEVERITY_POWER_LOW_WARNING:
+		case EV_SEVERITY_POWER_HIGH_WARNING:
+			pk_severity = KERN_WARNING;
+			break;
+		case EV_SEVERITY_POWER_HIGH_FAULT:
+		case EV_SEVERITY_POWER_LOW_FAULT:
+			pk_severity = KERN_ALERT;
+			break;
+		}
+		break;
+	case EV_CLASS_FAN:
+		switch (ev_severity) {
+		case EV_SEVERITY_FAN_WARNING:
+			pk_severity = KERN_WARNING;
+			break;
+		case EV_SEVERITY_FAN_FAULT:
+			pk_severity = KERN_CRIT;
+			break;
+		}
+		break;
+	case EV_CLASS_TEMP:
+		switch (ev_severity) {
+		case EV_SEVERITY_TEMP_ADVISORY:
+			pk_severity = KERN_WARNING;
+			break;
+		case EV_SEVERITY_TEMP_CRITICAL:
+			pk_severity = KERN_CRIT;
+			break;
+		case EV_SEVERITY_TEMP_FAULT:
+			pk_severity = KERN_ALERT;
+			break;
+		}
+		break;
+	case EV_CLASS_ENV:
+		pk_severity = KERN_ALERT;
+		break;
+	case EV_CLASS_TEST_FAULT:
+		pk_severity = KERN_ALERT;
+		break;
+	case EV_CLASS_TEST_WARNING:
+		pk_severity = KERN_WARNING;
+		break;
+	case EV_CLASS_PWRD_NOTIFY:
+		pk_severity = KERN_ALERT;
+		break;
+	}
+
+	return pk_severity;
+}
+
+
+/*
+ * scdrv_dispatch_event
+ *
+ * Do the right thing with an incoming event.  That's often nothing
+ * more than printing it to the system log.  For power-down notifications
+ * we start a graceful shutdown.
+ */
+static void
+scdrv_dispatch_event(char *event, int len)
+{
+	int code, esp_code, src;
+	char desc[CHUNKSIZE];
+	char *severity;
+
+	if (scdrv_parse_event(event, &src, &code, &esp_code, desc) < 0) {
+		/* ignore uninterpretible event */
+		return;
+	}
+
+	/* how urgent is the message? */
+	severity = scdrv_event_severity(code);
+
+	if ((code & EV_CLASS_MASK) == EV_CLASS_PWRD_NOTIFY) {
+		struct task_struct *p;
+
+		/* give a SIGPWR signal to init proc */
+
+		/* first find init's task */
+		read_lock(&tasklist_lock);
+		for_each_process(p) {
+			if (p->pid == 1)
+				break;
+		}
+		if (p) { /* we found init's task */
+			printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n");
+			force_sig(SIGPWR, p);
+		} else { /* failed to find init's task - just give message(s) */
+			printk(KERN_WARNING "Failed to find init proc to handle power off!\n");
+			printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
+		}
+		read_unlock(&tasklist_lock);
+	} else {
+		/* print to system log */
+		printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
+	}
+}
+
+
+/*
+ * scdrv_event
+ *
+ * Called as a tasklet when an event arrives from the L1.  Read the event
+ * from where it's temporarily stored in SAL and call scdrv_dispatch_event()
+ * to send it on its way.  Keep trying to read events until SAL indicates
+ * that there are no more immediately available.
+ */
+void
+scdrv_event(unsigned long dummy)
+{
+	int status;
+	int len;
+	unsigned long flags;
+	struct subch_data_s *sd = event_sd;
+
+	/* anything to read? */
+	len = CHUNKSIZE;
+	spin_lock_irqsave(&sd->sd_rlock, flags);
+	status = ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch,
+				   sd->sd_rb, &len);
+
+	while (!(status < 0)) {
+		spin_unlock_irqrestore(&sd->sd_rlock, flags);
+		scdrv_dispatch_event(sd->sd_rb, len);
+		len = CHUNKSIZE;
+		spin_lock_irqsave(&sd->sd_rlock, flags);
+		status = ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch,
+					   sd->sd_rb, &len);
+	}
+	spin_unlock_irqrestore(&sd->sd_rlock, flags);
+}
+
+
+/*
+ * scdrv_event_init
+ *
+ * Sets up a system controller subchannel to begin receiving event
+ * messages. This is sort of a specialized version of scdrv_open()
+ * in drivers/char/sn_sysctl.c.
+ */
+void
+scdrv_event_init(struct sysctl_data_s *scd)
+{
+	int rv;
+
+	event_sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+	if (event_sd == NULL) {
+		printk(KERN_WARNING "%s: couldn't allocate subchannel info"
+		       " for event monitoring\n", __FUNCTION__);
+		return;
+	}
+
+	/* initialize subch_data_s fields */
+	memset(event_sd, 0, sizeof (struct subch_data_s));
+	event_sd->sd_nasid = scd->scd_nasid;
+	spin_lock_init(&event_sd->sd_rlock);
+
+	/* ask the system controllers to send events to this node */
+	event_sd->sd_subch = ia64_sn_sysctl_event_init(scd->scd_nasid);
+
+	if (event_sd->sd_subch < 0) {
+		kfree(event_sd);
+		printk(KERN_WARNING "%s: couldn't open event subchannel\n",
+		       __FUNCTION__);
+		return;
+	}
+
+	/* hook event subchannel up to the system controller interrupt */
+	rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt,
+			 SA_SHIRQ | SA_INTERRUPT,
+			 "system controller events", event_sd);
+	if (rv) {
+		printk(KERN_WARNING "%s: irq request failed (%d)\n",
+		       __FUNCTION__, rv);
+		ia64_sn_irtr_close(event_sd->sd_nasid, event_sd->sd_subch);
+		kfree(event_sd);
+		return;
+	}
+}
+
+
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index c812191..fd04206 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1021,11 +1021,11 @@
 			ret = -EIO;
 			break;
 		}
-		if (copy_to_user((u8 *)arg, &val8, sizeof(val8)))
+		if (copy_to_user(argp, &val8, sizeof(val8)))
 			ret = -EFAULT;
 		break;
 	case SONYPI_IOCSFAN:
-		if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
+		if (copy_from_user(&val8, argp, sizeof(val8))) {
 			ret = -EFAULT;
 			break;
 		}
@@ -1038,7 +1038,7 @@
 			ret = -EIO;
 			break;
 		}
-		if (copy_to_user((u8 *)arg, &val8, sizeof(val8)))
+		if (copy_to_user(argp, &val8, sizeof(val8)))
 			ret = -EFAULT;
 		break;
 	default:
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index c789d5c..50e0b61 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1987,10 +1987,9 @@
 
 	func_enter();
 	/*
-	error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp));
-	if (error) {
+	if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
 		func_exit();
-		return error;
+		return -EFAULT;
 	}
 	*/
 	if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
@@ -2046,14 +2045,12 @@
 {
 	struct serial_struct tmp;
 	struct specialix_board *bp = port_Board(port);
-	//	int error;
 	
 	func_enter();
 
 	/*
-	error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp));
-	if (error)
-		return error;
+	if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
+		return -EFAULT;
 	*/
 
 	memset(&tmp, 0, sizeof(tmp));
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index de16660..b8899f5 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -466,7 +466,7 @@
 
 static unsigned long stl_atol(char *str);
 
-int		stl_init(void);
+static int	stl_init(void);
 static int	stl_open(struct tty_struct *tty, struct file *filp);
 static void	stl_close(struct tty_struct *tty, struct file *filp);
 static int	stl_write(struct tty_struct *tty, const unsigned char *buf, int count);
@@ -3063,7 +3063,7 @@
 
 /*****************************************************************************/
 
-int __init stl_init(void)
+static int __init stl_init(void)
 {
 	int i;
 	printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index ca36087..8723533 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -143,7 +143,7 @@
 		return -ENODATA;
 	if (count > bufsiz) {
 		dev_err(&chip->pci_dev->dev,
-			"invalid count value %x %x \n", count, bufsiz);
+			"invalid count value %x %zx \n", count, bufsiz);
 		return -E2BIG;
 	}
 
@@ -151,7 +151,7 @@
 
 	if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
 		dev_err(&chip->pci_dev->dev,
-			"tpm_transmit: tpm_send: error %d\n", len);
+			"tpm_transmit: tpm_send: error %zd\n", len);
 		return len;
 	}
 
@@ -188,7 +188,7 @@
 	len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
 	if (len < 0)
 		dev_err(&chip->pci_dev->dev,
-			"tpm_transmit: tpm_recv: error %d\n", len);
+			"tpm_transmit: tpm_recv: error %zd\n", len);
 	up(&chip->tpm_mutex);
 	return len;
 }
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 06e5a3f..26e5e19 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -185,7 +185,7 @@
 
 EXPORT_SYMBOL(tty_name);
 
-inline int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
+int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
 			      const char *routine)
 {
 #ifdef TTY_PARANOIA_CHECK
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 5d386f4..8971484 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -24,6 +24,7 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/console.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -641,7 +642,7 @@
 		extern int spawnpid, spawnsig;
 		if (!perm || !capable(CAP_KILL))
 		  return -EPERM;
-		if (arg < 1 || arg > _NSIG || arg == SIGKILL)
+		if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
 		  return -EINVAL;
 		spawnpid = current->pid;
 		spawnsig = arg;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b30001f..8e56131 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -223,7 +223,7 @@
 	}
 	if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
 	    (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
-	    (val == CPUFREQ_RESUMECHANGE)) {
+	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
 		dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new);
 	}
@@ -866,11 +866,90 @@
 
 
 /**
+ *	cpufreq_suspend - let the low level driver prepare for suspend
+ */
+
+static int cpufreq_suspend(struct sys_device * sysdev, u32 state)
+{
+	int cpu = sysdev->id;
+	unsigned int ret = 0;
+	unsigned int cur_freq = 0;
+	struct cpufreq_policy *cpu_policy;
+
+	dprintk("resuming cpu %u\n", cpu);
+
+	if (!cpu_online(cpu))
+		return 0;
+
+	/* we may be lax here as interrupts are off. Nonetheless
+	 * we need to grab the correct cpu policy, as to check
+	 * whether we really run on this CPU.
+	 */
+
+	cpu_policy = cpufreq_cpu_get(cpu);
+	if (!cpu_policy)
+		return -EINVAL;
+
+	/* only handle each CPU group once */
+	if (unlikely(cpu_policy->cpu != cpu)) {
+		cpufreq_cpu_put(cpu_policy);
+		return 0;
+	}
+
+	if (cpufreq_driver->suspend) {
+		ret = cpufreq_driver->suspend(cpu_policy, state);
+		if (ret) {
+			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
+					"step on CPU %u\n", cpu_policy->cpu);
+			cpufreq_cpu_put(cpu_policy);
+			return ret;
+		}
+	}
+
+
+	if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)
+		goto out;
+
+	if (cpufreq_driver->get)
+		cur_freq = cpufreq_driver->get(cpu_policy->cpu);
+
+	if (!cur_freq || !cpu_policy->cur) {
+		printk(KERN_ERR "cpufreq: suspend failed to assert current "
+		       "frequency is what timing core thinks it is.\n");
+		goto out;
+	}
+
+	if (unlikely(cur_freq != cpu_policy->cur)) {
+		struct cpufreq_freqs freqs;
+
+		if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
+			printk(KERN_DEBUG "Warning: CPU frequency is %u, "
+			       "cpufreq assumed %u kHz.\n",
+			       cur_freq, cpu_policy->cur);
+
+		freqs.cpu = cpu;
+		freqs.old = cpu_policy->cur;
+		freqs.new = cur_freq;
+
+		notifier_call_chain(&cpufreq_transition_notifier_list,
+				    CPUFREQ_SUSPENDCHANGE, &freqs);
+		adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
+
+		cpu_policy->cur = cur_freq;
+	}
+
+ out:
+	cpufreq_cpu_put(cpu_policy);
+	return 0;
+}
+
+/**
  *	cpufreq_resume -  restore proper CPU frequency handling after resume
  *
  *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
  *	2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync
- *	3.) schedule call cpufreq_update_policy() ASAP as interrupts are restored.
+ *	3.) schedule call cpufreq_update_policy() ASAP as interrupts are
+ *	    restored.
  */
 static int cpufreq_resume(struct sys_device * sysdev)
 {
@@ -915,21 +994,26 @@
 			cur_freq = cpufreq_driver->get(cpu_policy->cpu);
 
 		if (!cur_freq || !cpu_policy->cur) {
-			printk(KERN_ERR "cpufreq: resume failed to assert current frequency is what timing core thinks it is.\n");
+			printk(KERN_ERR "cpufreq: resume failed to assert "
+					"current frequency is what timing core "
+					"thinks it is.\n");
 			goto out;
 		}
 
 		if (unlikely(cur_freq != cpu_policy->cur)) {
 			struct cpufreq_freqs freqs;
 
-			printk(KERN_WARNING "Warning: CPU frequency is %u, "
-			       "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur);
+			if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
+				printk(KERN_WARNING "Warning: CPU frequency"
+				       "is %u, cpufreq assumed %u kHz.\n",
+				       cur_freq, cpu_policy->cur);
 
 			freqs.cpu = cpu;
 			freqs.old = cpu_policy->cur;
 			freqs.new = cur_freq;
 
-			notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs);
+			notifier_call_chain(&cpufreq_transition_notifier_list,
+					CPUFREQ_RESUMECHANGE, &freqs);
 			adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
 
 			cpu_policy->cur = cur_freq;
@@ -945,6 +1029,7 @@
 static struct sysdev_driver cpufreq_sysdev_driver = {
 	.add		= cpufreq_add_dev,
 	.remove		= cpufreq_remove_dev,
+	.suspend	= cpufreq_suspend,
 	.resume		= cpufreq_resume,
 };
 
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a2827e4..a0018de 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -237,7 +237,7 @@
 
 config I2C_MPC
 	tristate "MPC107/824x/85xx/52xx"
-	depends on I2C && PPC
+	depends on I2C && PPC32
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 75b8d86..6f33496 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -55,7 +55,7 @@
 #define CSR_RXAK 0x01
 
 struct mpc_i2c {
-	char *base;
+	void __iomem *base;
 	u32 interrupt;
 	wait_queue_head_t queue;
 	struct i2c_adapter adap;
@@ -444,7 +444,7 @@
 
       fail_add:
 	if (i2c->irq != 0)
-		free_irq(i2c->irq, 0);
+		free_irq(i2c->irq, NULL);
       fail_irq:
 	iounmap(i2c->base);
       fail_map:
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 9d70ba5..16b3e2d 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -726,7 +726,7 @@
 */
 
 /* Chip detection and general config */
-static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name)
+static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
 {
 	struct pci_dev *host;
 	int i = 0;
@@ -879,7 +879,7 @@
 	return 0;
 }
 
-static unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
+static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
 {
 	u8 ata66 = 0;
 
@@ -897,7 +897,7 @@
         return ata66;
 }
 
-static void __init init_hwif_sis5513 (ide_hwif_t *hwif)
+static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
 {
 	hwif->autodma = 0;
 
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 6dc273a..569f167 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1204,6 +1204,8 @@
 	}
 #endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
 
+	disable_irq(pmif->irq);
+
 	/* The media bay will handle itself just fine */
 	if (pmif->mediabay)
 		return 0;
@@ -1236,7 +1238,6 @@
 		ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
 		msleep(10);
 		ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0);
-		msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
 
 		/* Kauai has it different */
 		if (pmif->kauai_fcr) {
@@ -1244,11 +1245,15 @@
 			fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE;
 			writel(fcr, pmif->kauai_fcr);
 		}
+
+		msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
 	}
 
 	/* Sanitize drive timings */
 	sanitize_timings(pmif);
 
+	enable_irq(pmif->irq);
+
 	return 0;
 }
 
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 97ff364..6cb0b58 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -539,10 +539,8 @@
 	initialize_dma_trm_ctx(&ohci->at_req_context);
 	initialize_dma_trm_ctx(&ohci->at_resp_context);
 	
-	/* Initialize IR Legacy DMA */
+	/* Initialize IR Legacy DMA channel mask */
 	ohci->ir_legacy_channels = 0;
-	initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-	DBGMSG("ISO receive legacy context activated");
 
 	/*
 	 * Accept AT requests from all nodes. This probably
@@ -1032,6 +1030,8 @@
 	case ISO_LISTEN_CHANNEL:
         {
 		u64 mask;
+		struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
+		int ir_legacy_active;
 
 		if (arg<0 || arg>63) {
 			PRINT(KERN_ERR,
@@ -1052,9 +1052,37 @@
 			return -EFAULT;
 		}
 
+		ir_legacy_active = ohci->ir_legacy_channels;
+
 		ohci->ISO_channel_usage |= mask;
 		ohci->ir_legacy_channels |= mask;
 
+                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+
+		if (!ir_legacy_active) {
+			if (ohci1394_register_iso_tasklet(ohci,
+					  &ohci->ir_legacy_tasklet) < 0) {
+				PRINT(KERN_ERR, "No IR DMA context available");
+				return -EBUSY;
+			}
+
+			/* the IR context can be assigned to any DMA context
+			 * by ohci1394_register_iso_tasklet */
+			d->ctx = ohci->ir_legacy_tasklet.context;
+			d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
+				32*d->ctx;
+			d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
+				32*d->ctx;
+			d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
+			d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
+
+			initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
+
+			PRINT(KERN_ERR, "IR legacy activated");
+		}
+
+                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+
 		if (arg>31)
 			reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
 				  1<<(arg-32));
@@ -1101,6 +1129,12 @@
 
                 spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
                 DBGMSG("Listening disabled on channel %d", arg);
+
+		if (ohci->ir_legacy_channels == 0) {
+			stop_dma_rcv_ctx(&ohci->ir_legacy_context);
+			DBGMSG("ISO legacy receive context stopped");
+		}
+
                 break;
         }
 	default:
@@ -1270,8 +1304,10 @@
 				                       OHCI_ISO_RECEIVE,
 				  ohci_iso_recv_task, (unsigned long) iso);
 
-	if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0)
+	if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) {
+		ret = -EBUSY;
 		goto err;
+	}
 
 	recv->task_active = 1;
 
@@ -1896,8 +1932,10 @@
 	ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT,
 				  ohci_iso_xmit_task, (unsigned long) iso);
 
-	if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0)
+	if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) {
+		ret = -EBUSY;
 		goto err;
+	}
 
 	xmit->task_active = 1;
 
@@ -2691,7 +2729,7 @@
 				(cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
 				(cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
 				tcode, length, d->ctx,
-				(cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>10)&0x3f);
+				(cond_le32_to_cpu(d->spb[0], ohci->no_swap_incoming)>>10)&0x3f);
 
 			ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
 				== 0x11) ? 1 : 0;
@@ -2754,7 +2792,7 @@
 				       d->ctx);
 			else
 				DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
-				       "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d",
+				       "%d ack=0x%X spd=%d dataLength=%d ctx=%d",
 				       (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f,
 				       (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
 				       (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>10)&0x3f,
@@ -2763,7 +2801,7 @@
 				       d->ctx);
 		else
 			DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
-			       "0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d",
+			       "%d ack=0x%X spd=%d data=0x%08X ctx=%d",
                                 (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])
                                         >>16)&0x3f,
                                 (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
@@ -2999,20 +3037,6 @@
 		ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
 					  OHCI_ISO_MULTICHANNEL_RECEIVE,
 					  dma_rcv_tasklet, (unsigned long) d);
-		if (ohci1394_register_iso_tasklet(ohci,
-						  &ohci->ir_legacy_tasklet) < 0) {
-			PRINT(KERN_ERR, "No IR DMA context available");
-			free_dma_rcv_ctx(d);
-			return -EBUSY;
-		}
-
-		/* the IR context can be assigned to any DMA context
-		 * by ohci1394_register_iso_tasklet */
-		d->ctx = ohci->ir_legacy_tasklet.context;
-		d->ctrlSet = OHCI1394_IsoRcvContextControlSet + 32*d->ctx;
-		d->ctrlClear = OHCI1394_IsoRcvContextControlClear + 32*d->ctx;
-		d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
-		d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
 	} else {
 		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
 		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
@@ -3413,7 +3437,6 @@
 
 	switch (ohci->init_state) {
 	case OHCI_INIT_DONE:
-		stop_dma_rcv_ctx(&ohci->ir_legacy_context);
 		hpsb_remove_host(ohci->host);
 
 		/* Clear out BUS Options */
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 5824b6d..637b30e 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -32,6 +32,8 @@
  * $Id$
  */
 
+#include <linux/mm.h>
+
 #include "mthca_memfree.h"
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index c76cf8f..874367b 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -116,7 +116,7 @@
 
 		case 'K':				/* Button data */
 			if (spaceorb->idx != 5) return;
-			for (i = 0; i < 7; i++)
+			for (i = 0; i < 6; i++)
 				input_report_key(dev, spaceorb_buttons[i], (data[2] >> i) & 1);
 
 			break;
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index f7304f0..ff66ed4 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -678,7 +678,7 @@
 	atkbd_disable(atkbd);
 
 	/* make sure we don't have a command in flight */
-	synchronize_kernel();
+	synchronize_sched();  /* Allow atkbd_interrupt()s to complete. */
 	flush_scheduled_work();
 
 	device_remove_file(&serio->dev, &atkbd_attr_extra);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 0616353..12dee8e 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -60,12 +60,12 @@
 
 static struct class_simple *capi_class;
 
-int capi_major = 68;		/* allocated */
+static int capi_major = 68;		/* allocated */
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 #define CAPINC_NR_PORTS	32
 #define CAPINC_MAX_PORTS	256
-int capi_ttymajor = 191;
-int capi_ttyminors = CAPINC_NR_PORTS;
+static int capi_ttymajor = 191;
+static int capi_ttyminors = CAPINC_NR_PORTS;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
 module_param_named(major, capi_major, uint, 0);
@@ -268,7 +268,7 @@
 	kfree(mp);
 }
 
-struct capiminor *capiminor_find(unsigned int minor)
+static struct capiminor *capiminor_find(unsigned int minor)
 {
 	struct list_head *l;
 	struct capiminor *p = NULL;
@@ -1166,7 +1166,7 @@
 	return room;
 }
 
-int capinc_tty_chars_in_buffer(struct tty_struct *tty)
+static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	if (!mp || !mp->nccip) {
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 16dc541..2cc8b27 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -89,14 +89,14 @@
 	return 0;
 }
 
-struct seq_operations seq_controller_ops = {
+static struct seq_operations seq_controller_ops = {
 	.start	= controller_start,
 	.next	= controller_next,
 	.stop	= controller_stop,
 	.show	= controller_show,
 };
 
-struct seq_operations seq_contrstats_ops = {
+static struct seq_operations seq_contrstats_ops = {
 	.start	= controller_start,
 	.next	= controller_next,
 	.stop	= controller_stop,
@@ -192,14 +192,14 @@
 	return 0;
 }
 
-struct seq_operations seq_applications_ops = {
+static struct seq_operations seq_applications_ops = {
 	.start	= applications_start,
 	.next	= applications_next,
 	.stop	= applications_stop,
 	.show	= applications_show,
 };
 
-struct seq_operations seq_applstats_ops = {
+static struct seq_operations seq_applstats_ops = {
 	.start	= applications_start,
 	.next	= applications_next,
 	.stop	= applications_stop,
@@ -287,7 +287,7 @@
 	return 0;
 }
 
-struct seq_operations seq_capi_driver_ops = {
+static struct seq_operations seq_capi_driver_ops = {
 	.start	= capi_driver_start,
 	.next	= capi_driver_next,
 	.stop	= capi_driver_stop,
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index 1eb1122..0bfd698 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -383,7 +383,7 @@
 /*************************************************/
 /* called from common module on an incoming call */
 /*************************************************/
-int isdn_divert_icall(isdn_ctrl *ic)
+static int isdn_divert_icall(isdn_ctrl *ic)
 { int retval = 0;
   unsigned long flags;
   struct call_struc *cs = NULL; 
@@ -552,7 +552,7 @@
 /****************************************************/
 /* put a address including address type into buffer */
 /****************************************************/
-int put_address(char *st, u_char *p, int len)
+static int put_address(char *st, u_char *p, int len)
 { u_char retval = 0;
   u_char adr_typ = 0; /* network standard */
 
@@ -595,7 +595,7 @@
 /*************************************/
 /* report a succesfull interrogation */
 /*************************************/
-int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
+static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
 { char *src = ic->parm.dss1_io.data;
   int restlen = ic->parm.dss1_io.datalen;
   int cnt = 1;
@@ -689,7 +689,7 @@
 /*********************************************/
 /* callback for protocol specific extensions */
 /*********************************************/
-int prot_stat_callback(isdn_ctrl *ic)
+static int prot_stat_callback(isdn_ctrl *ic)
 { struct call_struc *cs, *cs1;
   int i;
   unsigned long flags;
@@ -781,7 +781,7 @@
 /***************************/
 /* status callback from HL */
 /***************************/
-int isdn_divert_stat_callback(isdn_ctrl *ic)
+static int isdn_divert_stat_callback(isdn_ctrl *ic)
 { struct call_struc *cs, *cs1;
   unsigned long flags;
   int retval;
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index 1ac46c2..ba1d028 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -29,6 +29,7 @@
 #include <linux/timer.h>
 #include <linux/skbuff.h>
 #include <linux/wait.h>
+#include <asm/io.h>
 #include "hisax_if.h"
 #include "hfc4s8s_l1.h"
 
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 8f93d01..db654e8 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -555,6 +555,42 @@
 #endif /* CONFIG_PMAC_BACKLIGHT */
 			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down);
 			break;
+
+		case 0xc:	/* videomode switch */
+			input_report_key(&adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);
+			break;
+
+		case 0xd:	/* keyboard illumination toggle */
+			input_report_key(&adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);
+			break;
+
+		case 0xe:	/* keyboard illumination decrease */
+			input_report_key(&adbhid[id]->input, KEY_KBDILLUMDOWN, down);
+			break;
+
+		case 0xf:
+			switch (data[1]) {
+			case 0x8f:
+			case 0x0f:
+				/* keyboard illumination increase */
+				input_report_key(&adbhid[id]->input, KEY_KBDILLUMUP, down);
+				break;
+
+			case 0x7f:
+			case 0xff:
+				/* keypad overlay toogle */
+				break;
+
+			default:
+				printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
+				       data[0], data[1], data[2], data[3]);
+				break;
+			}
+			break;
+		default:
+			printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",
+			       data[0], data[1], data[2], data[3]);
+			break;
 		}
 	  }
 	  break;
@@ -775,6 +811,10 @@
 			set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit);
 			set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit);
 			set_bit(KEY_EJECTCD, adbhid[id]->input.keybit);
+			set_bit(KEY_SWITCHVIDEOMODE, adbhid[id]->input.keybit);
+			set_bit(KEY_KBDILLUMTOGGLE, adbhid[id]->input.keybit);
+			set_bit(KEY_KBDILLUMDOWN, adbhid[id]->input.keybit);
+			set_bit(KEY_KBDILLUMUP, adbhid[id]->input.keybit);
 			break;
 		}
 		if (adbhid[id]->name[0])
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index fdea1a3..e654aa5 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2351,6 +2351,10 @@
 		return -EBUSY;
 	}
 
+	/* Disable clock spreading on some machines */
+	pmac_tweak_clock_spreading(0);
+
+	/* Stop preemption */
 	preempt_disable();
 
 	/* Make sure the decrementer won't interrupt us */
@@ -2417,11 +2421,12 @@
 
 	/* Re-enable local CPU interrupts */
 	local_irq_enable();
-
 	mdelay(100);
-
 	preempt_enable();
 
+	/* Re-enable clock spreading on some machines */
+	pmac_tweak_clock_spreading(1);
+
 	/* Resume devices */
 	device_resume();
 
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 77619a5..0dd6c2b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -331,25 +331,19 @@
 	struct bio *bio;
 	unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
-	unsigned long flags = current->flags;
 	unsigned int i;
 
 	/*
-	 * Tell VM to act less aggressively and fail earlier.
-	 * This is not necessary but increases throughput.
+	 * Use __GFP_NOMEMALLOC to tell the VM to act less aggressively and
+	 * to fail earlier.  This is not necessary but increases throughput.
 	 * FIXME: Is this really intelligent?
 	 */
-	current->flags &= ~PF_MEMALLOC;
-
 	if (base_bio)
-		bio = bio_clone(base_bio, GFP_NOIO);
+		bio = bio_clone(base_bio, GFP_NOIO|__GFP_NOMEMALLOC);
 	else
-		bio = bio_alloc(GFP_NOIO, nr_iovecs);
-	if (!bio) {
-		if (flags & PF_MEMALLOC)
-			current->flags |= PF_MEMALLOC;
+		bio = bio_alloc(GFP_NOIO|__GFP_NOMEMALLOC, nr_iovecs);
+	if (!bio)
 		return NULL;
-	}
 
 	/* if the last bio was not complete, continue where that one ended */
 	bio->bi_idx = *bio_vec_idx;
@@ -386,9 +380,6 @@
 		size -= bv->bv_len;
 	}
 
-	if (flags & PF_MEMALLOC)
-		current->flags |= PF_MEMALLOC;
-
 	if (!bio->bi_size) {
 		bio_put(bio);
 		return NULL;
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
index 7006586..c706767 100644
--- a/drivers/md/dm-emc.c
+++ b/drivers/md/dm-emc.c
@@ -223,8 +223,10 @@
 {
 	struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL);
 
-	if (h)
+	if (h) {
+		memset(h, 0, sizeof(*h));
 		spin_lock_init(&h->lock);
+	}
 
 	return h;
 }
@@ -259,8 +261,6 @@
 	if (!h)
 		return -ENOMEM;
 
-	memset(h, 0, sizeof(*h));
-
 	hwh->context = h;
 
 	if ((h->short_trespass = short_trespass))
diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c
index ae63772..4cc0010 100644
--- a/drivers/md/dm-hw-handler.c
+++ b/drivers/md/dm-hw-handler.c
@@ -23,7 +23,7 @@
 static LIST_HEAD(_hw_handlers);
 static DECLARE_RWSEM(_hwh_lock);
 
-struct hwh_internal *__find_hw_handler_type(const char *name)
+static struct hwh_internal *__find_hw_handler_type(const char *name)
 {
 	struct hwh_internal *hwhi;
 
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 43763a0..1e97b3c 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -101,6 +101,7 @@
 
 static kmem_cache_t *_mpio_cache;
 
+struct workqueue_struct *kmultipathd;
 static void process_queued_ios(void *data);
 static void trigger_event(void *data);
 
@@ -308,7 +309,7 @@
 		bio_list_add(&m->queued_ios, bio);
 		m->queue_size++;
 		if (m->pg_init_required || !m->queue_io)
-			schedule_work(&m->process_queued_ios);
+			queue_work(kmultipathd, &m->process_queued_ios);
 		pgpath = NULL;
 		r = 0;
 	} else if (!pgpath)
@@ -334,7 +335,7 @@
 
 	m->queue_if_no_path = queue_if_no_path;
 	if (!m->queue_if_no_path)
-		schedule_work(&m->process_queued_ios);
+		queue_work(kmultipathd, &m->process_queued_ios);
 
 	spin_unlock_irqrestore(&m->lock, flags);
 
@@ -800,7 +801,7 @@
 	if (pgpath == m->current_pgpath)
 		m->current_pgpath = NULL;
 
-	schedule_work(&m->trigger_event);
+	queue_work(kmultipathd, &m->trigger_event);
 
 out:
 	spin_unlock_irqrestore(&m->lock, flags);
@@ -837,9 +838,9 @@
 
 	m->current_pgpath = NULL;
 	if (!m->nr_valid_paths++)
-		schedule_work(&m->process_queued_ios);
+		queue_work(kmultipathd, &m->process_queued_ios);
 
-	schedule_work(&m->trigger_event);
+	queue_work(kmultipathd, &m->trigger_event);
 
 out:
 	spin_unlock_irqrestore(&m->lock, flags);
@@ -883,7 +884,7 @@
 
 	spin_unlock_irqrestore(&m->lock, flags);
 
-	schedule_work(&m->trigger_event);
+	queue_work(kmultipathd, &m->trigger_event);
 }
 
 /*
@@ -913,7 +914,7 @@
 	}
 	spin_unlock_irqrestore(&m->lock, flags);
 
-	schedule_work(&m->trigger_event);
+	queue_work(kmultipathd, &m->trigger_event);
 	return 0;
 }
 
@@ -968,7 +969,7 @@
 		m->current_pgpath = NULL;
 		m->current_pg = NULL;
 	}
-	schedule_work(&m->process_queued_ios);
+	queue_work(kmultipathd, &m->process_queued_ios);
 	spin_unlock_irqrestore(&m->lock, flags);
 }
 
@@ -1018,7 +1019,7 @@
 	bio_list_add(&m->queued_ios, bio);
 	m->queue_size++;
 	if (!m->queue_io)
-		schedule_work(&m->process_queued_ios);
+		queue_work(kmultipathd, &m->process_queued_ios);
 	spin_unlock(&m->lock);
 
 	return 1;	/* io not complete */
@@ -1057,7 +1058,7 @@
 	spin_lock_irqsave(&m->lock, flags);
 	m->suspended = 1;
 	if (m->queue_if_no_path)
-		schedule_work(&m->process_queued_ios);
+		queue_work(kmultipathd, &m->process_queued_ios);
 	spin_unlock_irqrestore(&m->lock, flags);
 }
 
@@ -1274,6 +1275,15 @@
 		return -EINVAL;
 	}
 
+	kmultipathd = create_workqueue("kmpathd");
+	if (!kmultipathd) {
+		DMERR("%s: failed to create workqueue kmpathd",
+				multipath_target.name);
+		dm_unregister_target(&multipath_target);
+		kmem_cache_destroy(_mpio_cache);
+		return -ENOMEM;
+	}
+
 	DMINFO("dm-multipath version %u.%u.%u loaded",
 	       multipath_target.version[0], multipath_target.version[1],
 	       multipath_target.version[2]);
@@ -1285,6 +1295,8 @@
 {
 	int r;
 
+	destroy_workqueue(kmultipathd);
+
 	r = dm_unregister_target(&multipath_target);
 	if (r < 0)
 		DMERR("%s: target unregister failed %d",
diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c
index ac5c4bb..a28c1c2 100644
--- a/drivers/md/dm-path-selector.c
+++ b/drivers/md/dm-path-selector.c
@@ -26,7 +26,7 @@
 static LIST_HEAD(_path_selectors);
 static DECLARE_RWSEM(_ps_lock);
 
-struct ps_internal *__find_path_selector_type(const char *name)
+static struct ps_internal *__find_path_selector_type(const char *name)
 {
 	struct ps_internal *psi;
 
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index ee175d4..18e9b99 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -242,7 +242,7 @@
 	}
 }
 
-void table_destroy(struct dm_table *t)
+static void table_destroy(struct dm_table *t)
 {
 	unsigned int i;
 
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index 7febc2c..51c0639 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -55,7 +55,7 @@
 	.map    = zero_map,
 };
 
-int __init dm_zero_init(void)
+static int __init dm_zero_init(void)
 {
 	int r = dm_register_target(&zero_target);
 
@@ -65,7 +65,7 @@
 	return r;
 }
 
-void __exit dm_zero_exit(void)
+static void __exit dm_zero_exit(void)
 {
 	int r = dm_unregister_target(&zero_target);
 
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 243ff68..f6b0395 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -97,6 +97,7 @@
 	 * freeze/thaw support require holding onto a super block
 	 */
 	struct super_block *frozen_sb;
+	struct block_device *frozen_bdev;
 };
 
 #define MIN_IOS 256
@@ -990,44 +991,50 @@
  */
 static int __lock_fs(struct mapped_device *md)
 {
-	struct block_device *bdev;
+	int error = -ENOMEM;
 
 	if (test_and_set_bit(DMF_FS_LOCKED, &md->flags))
 		return 0;
 
-	bdev = bdget_disk(md->disk, 0);
-	if (!bdev) {
+	md->frozen_bdev = bdget_disk(md->disk, 0);
+	if (!md->frozen_bdev) {
 		DMWARN("bdget failed in __lock_fs");
-		return -ENOMEM;
+		goto out;
 	}
 
 	WARN_ON(md->frozen_sb);
-	md->frozen_sb = freeze_bdev(bdev);
+
+	md->frozen_sb = freeze_bdev(md->frozen_bdev);
+	if (IS_ERR(md->frozen_sb)) {
+		error = PTR_ERR(md->frozen_sb);
+		goto out_bdput;
+	}
+
 	/* don't bdput right now, we don't want the bdev
 	 * to go away while it is locked.  We'll bdput
 	 * in __unlock_fs
 	 */
 	return 0;
+
+out_bdput:
+	bdput(md->frozen_bdev);
+	md->frozen_sb = NULL;
+	md->frozen_bdev = NULL;
+out:
+	clear_bit(DMF_FS_LOCKED, &md->flags);
+	return error;
 }
 
-static int __unlock_fs(struct mapped_device *md)
+static void __unlock_fs(struct mapped_device *md)
 {
-	struct block_device *bdev;
-
 	if (!test_and_clear_bit(DMF_FS_LOCKED, &md->flags))
-		return 0;
+		return;
 
-	bdev = bdget_disk(md->disk, 0);
-	if (!bdev) {
-		DMWARN("bdget failed in __unlock_fs");
-		return -ENOMEM;
-	}
+	thaw_bdev(md->frozen_bdev, md->frozen_sb);
+	bdput(md->frozen_bdev);
 
-	thaw_bdev(bdev, md->frozen_sb);
 	md->frozen_sb = NULL;
-	bdput(bdev);
-	bdput(bdev);
-	return 0;
+	md->frozen_bdev = NULL;
 }
 
 /*
@@ -1041,37 +1048,37 @@
 {
 	struct dm_table *map;
 	DECLARE_WAITQUEUE(wait, current);
+	int error = -EINVAL;
 
 	/* Flush I/O to the device. */
 	down_read(&md->lock);
-	if (test_bit(DMF_BLOCK_IO, &md->flags)) {
-		up_read(&md->lock);
-		return -EINVAL;
-	}
+	if (test_bit(DMF_BLOCK_IO, &md->flags))
+		goto out_read_unlock;
+
+	error = __lock_fs(md);
+	if (error)
+		goto out_read_unlock;
 
 	map = dm_get_table(md);
 	if (map)
 		dm_table_presuspend_targets(map);
-	__lock_fs(md);
 
 	up_read(&md->lock);
 
 	/*
-	 * First we set the BLOCK_IO flag so no more ios will be
-	 * mapped.
+	 * First we set the BLOCK_IO flag so no more ios will be mapped.
+	 *
+	 * If the flag is already set we know another thread is trying to
+	 * suspend as well, so we leave the fs locked for this thread.
 	 */
+	error = -EINVAL;
 	down_write(&md->lock);
-	if (test_bit(DMF_BLOCK_IO, &md->flags)) {
-		/*
-		 * If we get here we know another thread is
-		 * trying to suspend as well, so we leave the fs
-		 * locked for this thread.
-		 */
-		up_write(&md->lock);
-		return -EINVAL;
+	if (test_and_set_bit(DMF_BLOCK_IO, &md->flags)) {
+		if (map)
+			dm_table_put(map);
+		goto out_write_unlock;
 	}
 
-	set_bit(DMF_BLOCK_IO, &md->flags);
 	add_wait_queue(&md->wait, &wait);
 	up_write(&md->lock);
 
@@ -1099,12 +1106,9 @@
 	remove_wait_queue(&md->wait, &wait);
 
 	/* were we interrupted ? */
-	if (atomic_read(&md->pending)) {
-		__unlock_fs(md);
-		clear_bit(DMF_BLOCK_IO, &md->flags);
-		up_write(&md->lock);
-		return -EINTR;
-	}
+	error = -EINTR;
+	if (atomic_read(&md->pending))
+		goto out_unfreeze;
 
 	set_bit(DMF_SUSPENDED, &md->flags);
 
@@ -1115,6 +1119,18 @@
 	up_write(&md->lock);
 
 	return 0;
+
+out_unfreeze:
+	/* FIXME Undo dm_table_presuspend_targets */
+	__unlock_fs(md);
+	clear_bit(DMF_BLOCK_IO, &md->flags);
+out_write_unlock:
+	up_write(&md->lock);
+	return error;
+
+out_read_unlock:
+	up_read(&md->lock);
+	return error;
 }
 
 int dm_resume(struct mapped_device *md)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 97af857..d899204 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -957,7 +957,7 @@
 }
 
 
-struct super_type super_types[] = {
+static struct super_type super_types[] = {
 	[0] = {
 		.name	= "0.90.0",
 		.owner	= THIS_MODULE,
@@ -2740,7 +2740,7 @@
 	.revalidate_disk= md_revalidate,
 };
 
-int md_thread(void * arg)
+static int md_thread(void * arg)
 {
 	mdk_thread_t *thread = arg;
 
@@ -3232,7 +3232,7 @@
 }
 
 
-DECLARE_WAIT_QUEUE_HEAD(resync_wait);
+static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
 
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
@@ -3575,8 +3575,8 @@
 	}
 }
 
-int md_notify_reboot(struct notifier_block *this,
-					unsigned long code, void *x)
+static int md_notify_reboot(struct notifier_block *this,
+			    unsigned long code, void *x)
 {
 	struct list_head *tmp;
 	mddev_t *mddev;
@@ -3599,7 +3599,7 @@
 	return NOTIFY_DONE;
 }
 
-struct notifier_block md_notifier = {
+static struct notifier_block md_notifier = {
 	.notifier_call	= md_notify_reboot,
 	.next		= NULL,
 	.priority	= INT_MAX, /* before any real devices */
@@ -3616,7 +3616,7 @@
 		p->proc_fops = &md_seq_fops;
 }
 
-int __init md_init(void)
+static int __init md_init(void)
 {
 	int minor;
 
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index c9b134c..4e4bfde 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -103,7 +103,8 @@
 	mempool_free(mp_bh, conf->pool);
 }
 
-int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error)
+static int multipath_end_request(struct bio *bio, unsigned int bytes_done,
+				 int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 	struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private);
@@ -355,7 +356,7 @@
 			goto abort;
 		}
 		p->rdev = NULL;
-		synchronize_kernel();
+		synchronize_rcu();
 		if (atomic_read(&rdev->nr_pending)) {
 			/* lost the race, try later */
 			err = -EBUSY;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index a389394..83380b5 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -797,7 +797,7 @@
 			goto abort;
 		}
 		p->rdev = NULL;
-		synchronize_kernel();
+		synchronize_rcu();
 		if (atomic_read(&rdev->nr_pending)) {
 			/* lost the race, try later */
 			err = -EBUSY;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index b100bfe..e9dc287 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -977,7 +977,7 @@
 			goto abort;
 		}
 		p->rdev = NULL;
-		synchronize_kernel();
+		synchronize_rcu();
 		if (atomic_read(&rdev->nr_pending)) {
 			/* lost the race, try later */
 			err = -EBUSY;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 52c3a81..e96e2a1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1873,7 +1873,7 @@
 			goto abort;
 		}
 		p->rdev = NULL;
-		synchronize_kernel();
+		synchronize_rcu();
 		if (atomic_read(&rdev->nr_pending)) {
 			/* lost the race, try later */
 			err = -EBUSY;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 7e30ab2..8a33f35 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -2038,7 +2038,7 @@
 			goto abort;
 		}
 		p->rdev = NULL;
-		synchronize_kernel();
+		synchronize_rcu();
 		if (atomic_read(&rdev->nr_pending)) {
 			/* lost the race, try later */
 			err = -EBUSY;
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index 8c842e2..84a49d2 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -131,10 +131,10 @@
 	[ 18 ] = KEY_KP0,
 
 	[  0 ] = KEY_POWER,
-//      [ 27 ] = MTS button
+	[ 27 ] = KEY_LANGUAGE,  //MTS button
 	[  2 ] = KEY_TUNER,     // TV/FM
 	[ 30 ] = KEY_VIDEO,
-//      [ 22 ] = display button
+	[ 22 ] = KEY_INFO,      //display button
 	[  4 ] = KEY_VOLUMEUP,
 	[  8 ] = KEY_VOLUMEDOWN,
 	[ 12 ] = KEY_CHANNELUP,
@@ -142,7 +142,7 @@
 	[  3 ] = KEY_ZOOM,      // fullscreen
 	[ 31 ] = KEY_SUBTITLE,  // closed caption/teletext
 	[ 32 ] = KEY_SLEEP,
-//      [ 41 ] = boss key
+	[ 41 ] = KEY_SEARCH,    //boss key
 	[ 20 ] = KEY_MUTE,
 	[ 43 ] = KEY_RED,
 	[ 44 ] = KEY_GREEN,
@@ -150,17 +150,17 @@
 	[ 46 ] = KEY_BLUE,
 	[ 24 ] = KEY_KPPLUS,    //fine tune +
 	[ 25 ] = KEY_KPMINUS,   //fine tune -
-//      [ 42 ] = picture in picture
-        [ 33 ] = KEY_KPDOT,
+	[ 42 ] = KEY_ANGLE,     //picture in picture
+	[ 33 ] = KEY_KPDOT,
 	[ 19 ] = KEY_KPENTER,
-//      [ 17 ] = recall
+	[ 17 ] = KEY_AGAIN,     //recall
 	[ 34 ] = KEY_BACK,
 	[ 35 ] = KEY_PLAYPAUSE,
 	[ 36 ] = KEY_NEXT,
-//      [ 37 ] = time shifting
+	[ 37 ] = KEY_T,         //time shifting
 	[ 38 ] = KEY_STOP,
-	[ 39 ] = KEY_RECORD
-//      [ 40 ] = snapshot
+	[ 39 ] = KEY_RECORD,
+	[ 40 ] = KEY_SHUFFLE    //snapshot
 };
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 1930b51..011860c 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include "dvb_frontend.h"
+#include "dvb-pll.h"
 #include "cx22702.h"
 
 
@@ -203,7 +204,19 @@
 
 	/* set PLL */
         cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
-	state->config->pll_set(fe, p);
+	if (state->config->pll_set) {
+		state->config->pll_set(fe, p);
+	} else if (state->config->pll_desc) {
+		u8 pllbuf[4];
+		struct i2c_msg msg = { .addr = state->config->pll_address,
+				       .buf = pllbuf, .len = 4 };
+		dvb_pll_configure(state->config->pll_desc, pllbuf,
+				  p->frequency,
+				  p->u.ofdm.bandwidth);
+		i2c_transfer(state->i2c, &msg, 1);
+	} else {
+		BUG();
+	}
         cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
 
 	/* set inversion */
diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
index 6e34f99..559fdb9 100644
--- a/drivers/media/dvb/frontends/cx22702.h
+++ b/drivers/media/dvb/frontends/cx22702.h
@@ -36,6 +36,9 @@
 	u8 demod_address;
 
 	/* PLL maintenance */
+	u8 pll_address;
+	struct dvb_pll_desc *pll_desc;
+
 	int (*pll_init)(struct dvb_frontend* fe);
 	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index c1b3542..d3dd422 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -252,6 +252,7 @@
 	depends on VIDEO_SAA7134 && DVB_CORE
 	select VIDEO_BUF_DVB
 	select DVB_MT352
+	select DVB_CX22702
 	---help---
 	  This adds support for DVB cards based on the
 	  Philips saa7134 chip.
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index c13f222..033cc54 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -3169,7 +3169,7 @@
 /* ----------------------------------------------------------------------- */
 /* some debug code                                                         */
 
-int bttv_risc_decode(u32 risc)
+static int bttv_risc_decode(u32 risc)
 {
 	static char *instr[16] = {
 		[ BT848_RISC_WRITE     >> 28 ] = "write",
@@ -3206,8 +3206,8 @@
 	return incr[risc >> 28] ? incr[risc >> 28] : 1;
 }
 
-void bttv_risc_disasm(struct bttv *btv,
-		      struct btcx_riscmem *risc)
+static void bttv_risc_disasm(struct bttv *btv,
+			     struct btcx_riscmem *risc)
 {
 	unsigned int i,j,n;
 
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index e42f1ec1..e3f477d 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -29,6 +29,7 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <asm/io.h>
 
 #include "bttvp.h"
@@ -130,17 +131,14 @@
 static int
 bttv_i2c_wait_done(struct bttv *btv)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	int rc = 0;
 
-	add_wait_queue(&btv->i2c_queue, &wait);
-	if (0 == btv->i2c_done)
-		msleep_interruptible(20);
-	remove_wait_queue(&btv->i2c_queue, &wait);
+	/* timeout */
+	if (wait_event_interruptible_timeout(btv->i2c_queue,
+		btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS)
 
-	if (0 == btv->i2c_done)
-		/* timeout */
-		rc = -EIO;
+	rc = -EIO;
+
 	if (btv->i2c_done & BT848_INT_RACK)
 		rc = 1;
 	btv->i2c_done = 0;
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 26a6138..1ff79b5 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -429,7 +429,7 @@
 /* ------------------------------------------------------------------ */
 /* debug helper code                                                  */
 
-int cx88_risc_decode(u32 risc)
+static int cx88_risc_decode(u32 risc)
 {
 	static char *instr[16] = {
 		[ RISC_SYNC    >> 28 ] = "sync",
@@ -542,7 +542,7 @@
 	       core->name,cx_read(ch->cnt2_reg));
 }
 
-char *cx88_pci_irqs[32] = {
+static char *cx88_pci_irqs[32] = {
 	"vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
 	"src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
 	"brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
@@ -1206,7 +1206,6 @@
 /* ------------------------------------------------------------------ */
 
 EXPORT_SYMBOL(cx88_print_ioctl);
-EXPORT_SYMBOL(cx88_pci_irqs);
 EXPORT_SYMBOL(cx88_vid_irqs);
 EXPORT_SYMBOL(cx88_mpeg_irqs);
 EXPORT_SYMBOL(cx88_print_irqbits);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index bc6f18c..9d15d3d 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -31,7 +31,7 @@
 #include <linux/suspend.h>
 
 /* those two frontends need merging via linuxtv cvs ... */
-#define HAVE_CX22702 0
+#define HAVE_CX22702 1
 #define HAVE_OR51132 1
 
 #include "cx88.h"
@@ -91,7 +91,7 @@
 	cx88_free_buffer(dev->pci, (struct cx88_buffer*)vb);
 }
 
-struct videobuf_queue_ops dvb_qops = {
+static struct videobuf_queue_ops dvb_qops = {
 	.buf_setup    = dvb_buf_setup,
 	.buf_prepare  = dvb_buf_prepare,
 	.buf_queue    = dvb_buf_queue,
@@ -191,7 +191,7 @@
 	return 0;
 }
 
-struct or51132_config pchdtv_hd3000 = {
+static struct or51132_config pchdtv_hd3000 = {
 	.demod_address    = 0x15,
 	.pll_address      = 0x61,
 	.pll_desc         = &dvb_pll_thomson_dtt7610,
@@ -243,10 +243,8 @@
 		break;
 #endif
 	default:
-		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n"
-		       "%s: you might want to look out for patches here:\n"
-		       "%s:     http://dl.bytesex.org/patches/\n",
-		       dev->core->name, dev->core->name, dev->core->name);
+		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
+		       dev->core->name);
 		break;
 	}
 	if (NULL == dev->dvb.frontend) {
@@ -308,9 +306,11 @@
 			    dev);
 	err = dvb_register(dev);
 	if (0 != err)
-		goto fail_free;
+		goto fail_fini;
 	return 0;
 
+ fail_fini:
+	cx8802_fini_common(dev);
  fail_free:
 	kfree(dev);
  fail_core:
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 6080017..0725b12 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -45,7 +45,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-void cx8800_bit_setscl(void *data, int state)
+static void cx8800_bit_setscl(void *data, int state)
 {
 	struct cx88_core *core = data;
 
@@ -57,7 +57,7 @@
 	cx_read(MO_I2C);
 }
 
-void cx8800_bit_setsda(void *data, int state)
+static void cx8800_bit_setsda(void *data, int state)
 {
 	struct cx88_core *core = data;
 
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 471e508..0584ff4 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -46,9 +46,9 @@
 	}
 }
 
-int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-			 struct cx88_dmaqueue *q,
-			 struct cx88_buffer   *buf)
+static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
+				struct cx88_dmaqueue *q,
+				struct cx88_buffer   *buf)
 {
 	struct cx88_core *core = dev->core;
 
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 701f594..d1f5c92 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -325,7 +325,7 @@
 		.shift                 = 0,
 	}
 };
-const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
+static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
 
 /* ------------------------------------------------------------------- */
 /* resource management                                                 */
@@ -665,7 +665,7 @@
 	cx88_free_buffer(fh->dev->pci,buf);
 }
 
-struct videobuf_queue_ops cx8800_video_qops = {
+static struct videobuf_queue_ops cx8800_video_qops = {
 	.buf_setup    = buffer_setup,
 	.buf_prepare  = buffer_prepare,
 	.buf_queue    = buffer_queue,
@@ -1924,7 +1924,7 @@
 	.llseek        = no_llseek,
 };
 
-struct video_device cx8800_video_template =
+static struct video_device cx8800_video_template =
 {
 	.name          = "cx8800-video",
 	.type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
@@ -1933,7 +1933,7 @@
 	.minor         = -1,
 };
 
-struct video_device cx8800_vbi_template =
+static struct video_device cx8800_vbi_template =
 {
 	.name          = "cx8800-vbi",
 	.type          = VID_TYPE_TELETEXT|VID_TYPE_TUNER,
@@ -1951,7 +1951,7 @@
 	.llseek        = no_llseek,
 };
 
-struct video_device cx8800_radio_template =
+static struct video_device cx8800_radio_template =
 {
 	.name          = "cx8800-radio",
 	.type          = VID_TYPE_TUNER,
@@ -2226,7 +2226,7 @@
 
 /* ----------------------------------------------------------- */
 
-struct pci_device_id cx8800_pci_tbl[] = {
+static struct pci_device_id cx8800_pci_tbl[] = {
 	{
 		.vendor       = 0x14f1,
 		.device       = 0x8800,
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index b351d9e..88eaaab 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -420,7 +420,6 @@
 /* ----------------------------------------------------------- */
 /* cx88-core.c                                                 */
 
-extern char *cx88_pci_irqs[32];
 extern char *cx88_vid_irqs[32];
 extern char *cx88_mpeg_irqs[32];
 extern void cx88_print_irqbits(char *name, char *tag, char **strings,
@@ -472,9 +471,6 @@
 /* cx88-vbi.c                                                  */
 
 void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
-int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-			 struct cx88_dmaqueue *q,
-			 struct cx88_buffer   *buf);
 int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
 int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
 			     struct cx88_dmaqueue *q);
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index c97df70..7fbb858 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -380,7 +380,9 @@
 	int val = 0, bal = 0;
 
 	if (!muted) {
-		val = (volume * 0x7F / 65535) << 8;
+		/* 0x7f instead if 0x73 here has sound quality issues,
+		 * probably due to overmodulation + clipping ... */
+		val = (volume * 0x73 / 65535) << 8;
 	}
 	if (val) {
 		bal = (balance / 256) - 128;
@@ -997,7 +999,13 @@
 {
 	switch (norm) {
 	case VIDEO_MODE_PAL:
+#if 1
+		/* experimental: not sure this works with all chip versions */
+		return 0x7003;
+#else
+		/* previous value, try this if it breaks ... */
 		return 0x1003;
+#endif
 	case VIDEO_MODE_NTSC:  /* BTSC */
 		return 0x2003;
 	case VIDEO_MODE_SECAM:
@@ -1264,6 +1272,7 @@
 	int val, std, i;
 
 	printk("msp34xxg: daemon started\n");
+	msp->source = 1; /* default */
 	for (;;) {
 		d2printk(KERN_DEBUG "msp34xxg: thread: sleep\n");
 		msp34xx_sleep(msp,-1);
@@ -1334,8 +1343,9 @@
 
 	/* fix matrix mode to stereo and let the msp choose what
 	 * to output according to 'source', as recommended
+	 * for MONO (source==0) downmixing set bit[7:0] to 0x30
 	 */
-	int value = (source&0x07)<<8|(source==0 ? 0x00:0x20);
+	int value = (source&0x07)<<8|(source==0 ? 0x30:0x20);
 	dprintk("msp34xxg: set source to %d (0x%x)\n", source, value);
 	msp3400c_write(client,
 		       I2C_MSP3400C_DFP,
@@ -1359,7 +1369,7 @@
 	msp3400c_write(client,
 		       I2C_MSP3400C_DEM,
 		       0x22, /* a2 threshold for stereo/bilingual */
-		       source==0 ? 0x7f0:stereo_threshold);
+		       stereo_threshold);
 	msp->source=source;
 }
 
@@ -1394,7 +1404,7 @@
 static void msp34xxg_set_audmode(struct i2c_client *client, int audmode)
 {
 	struct msp3400c *msp = i2c_get_clientdata(client);
-	int source = 0;
+	int source;
 
 	switch (audmode) {
 	case V4L2_TUNER_MODE_MONO:
@@ -1410,9 +1420,10 @@
 	case V4L2_TUNER_MODE_LANG2:
 		source=4; /* stereo or B */
 		break;
-	default: /* doing nothing: a safe, sane default */
+	default:
 		audmode = 0;
-		return;
+		source  = 1;
+		break;
 	}
 	msp->audmode = audmode;
 	msp34xxg_set_source(client, source);
@@ -1514,12 +1525,9 @@
 
 	msp->opmode = opmode;
 	if (OPMODE_AUTO == msp->opmode) {
-#if 0 /* seems to work for ivtv only, disable by default for now ... */
 		if (HAVE_SIMPLER(msp))
 			msp->opmode = OPMODE_SIMPLER;
-		else
-#endif
-		if (HAVE_SIMPLE(msp))
+		else if (HAVE_SIMPLE(msp))
 			msp->opmode = OPMODE_SIMPLE;
 		else
 			msp->opmode = OPMODE_MANUAL;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index cee1358..fe6abe3 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -32,9 +32,32 @@
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
+enum saa6752hs_videoformat {
+	SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
+	SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
+	SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
+	SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
+	SAA6752HS_VF_UNKNOWN,
+};
+
+static const struct v4l2_format v4l2_format_table[] =
+{
+	[SAA6752HS_VF_D1] = {
+		.fmt.pix.width = 720, .fmt.pix.height = 576 },
+	[SAA6752HS_VF_2_3_D1] = {
+		.fmt.pix.width = 480, .fmt.pix.height = 576 },
+	[SAA6752HS_VF_1_2_D1] = {
+		.fmt.pix.width = 352, .fmt.pix.height = 576 },
+	[SAA6752HS_VF_SIF] = {
+		.fmt.pix.width = 352, .fmt.pix.height = 288 },
+	[SAA6752HS_VF_UNKNOWN] = {
+		.fmt.pix.width = 0, .fmt.pix.height = 0},
+};
+
 struct saa6752hs_state {
 	struct i2c_client             client;
 	struct v4l2_mpeg_compression  params;
+	enum saa6752hs_videoformat    video_format;
 };
 
 enum saa6752hs_command {
@@ -256,6 +279,51 @@
 	return 0;
 }
 
+static void saa6752hs_set_subsampling(struct i2c_client* client,
+				      struct v4l2_format* f)
+{
+	struct saa6752hs_state *h = i2c_get_clientdata(client);
+	int dist_352, dist_480, dist_720;
+
+	/*
+	  FIXME: translate and round width/height into EMPRESS
+	  subsample type:
+
+	  type   |   PAL   |  NTSC
+	  ---------------------------
+	  SIF    | 352x288 | 352x240
+	  1/2 D1 | 352x576 | 352x480
+	  2/3 D1 | 480x576 | 480x480
+	  D1     | 720x576 | 720x480
+	*/
+
+	dist_352 = abs(f->fmt.pix.width - 352);
+	dist_480 = abs(f->fmt.pix.width - 480);
+	dist_720 = abs(f->fmt.pix.width - 720);
+	if (dist_720 < dist_480) {
+		f->fmt.pix.width = 720;
+		f->fmt.pix.height = 576;
+		h->video_format = SAA6752HS_VF_D1;
+	}
+	else if (dist_480 < dist_352) {
+		f->fmt.pix.width = 480;
+		f->fmt.pix.height = 576;
+		h->video_format = SAA6752HS_VF_2_3_D1;
+	}
+	else {
+		f->fmt.pix.width = 352;
+		if (abs(f->fmt.pix.height - 576) <
+		    abs(f->fmt.pix.height - 288)) {
+			f->fmt.pix.height = 576;
+			h->video_format = SAA6752HS_VF_1_2_D1;
+		}
+		else {
+			f->fmt.pix.height = 288;
+			h->video_format = SAA6752HS_VF_SIF;
+		}
+	}
+}
+
 
 static void saa6752hs_set_params(struct i2c_client* client,
 				 struct v4l2_mpeg_compression* params)
@@ -315,7 +383,7 @@
 
 	// Set video format - must be done first as it resets other settings
 	buf[0] = 0x41;
-	buf[1] = 0 /* MPEG_VIDEO_FORMAT_D1 */;
+	buf[1] = h->video_format;
 	i2c_master_send(client, buf, 2);
 
         // set bitrate
@@ -494,6 +562,25 @@
 	case VIDIOC_G_MPEGCOMP:
 		*params = h->params;
 		break;
+	case VIDIOC_G_FMT:
+	{
+           struct v4l2_format *f = arg;
+
+	   if (h->video_format == SAA6752HS_VF_UNKNOWN)
+		   h->video_format = SAA6752HS_VF_D1;
+	   f->fmt.pix.width =
+		   v4l2_format_table[h->video_format].fmt.pix.width;
+	   f->fmt.pix.height =
+		   v4l2_format_table[h->video_format].fmt.pix.height;
+	   break ;
+	}
+	case VIDIOC_S_FMT:
+	{
+		struct v4l2_format *f = arg;
+
+		saa6752hs_set_subsampling(client, f);
+		break;
+	}
 	default:
 		/* nothing */
 		break;
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 180d317..c51eb7f 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -183,12 +183,12 @@
 		.name           = "LifeView FlyTV Platinum FM",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_TDA8290,
-//		.gpiomask       = 0xe000,
+		.gpiomask       = 0x1E000,	/* Set GP16 and unused 15,14,13 to Output */
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
 			.amux = TV,
-//			.gpio = 0x0000,
+			.gpio = 0x10000,	/* GP16=1 selects TV input */
 			.tv   = 1,
                 },{
 /*			.name = name_tv_mono,
@@ -212,12 +212,12 @@
 			.amux = LINE2,
 //			.gpio = 0x4000,
 		}},
-/*		.radio = {
+		.radio = {
 			.name = name_radio,
-			.amux = LINE2,
-			.gpio = 0x2000,
+			.amux = TV,
+			.gpio = 0x00000,	/* GP16=0 selects FM radio antenna */
 		},
-*/	},
+	},
 	[SAA7134_BOARD_EMPRESS] = {
 		/* "Gert Vervoort" <gert.vervoort@philips.com> */
 		.name		= "EMPRESS",
@@ -1628,11 +1628,17 @@
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-		.subvendor    = 0x5168,
+		.subvendor    = 0x5168,	/* Animation Technologies (LifeView) */
 		.subdevice    = 0x0214, /* Standard PCI, LR214WF */
 		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1489, /* KYE */
+		.subdevice    = 0x0214, /* Genius VideoWonder ProTV */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM, /* is an LR214WF actually */
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x16be,
 		.subdevice    = 0x0003,
@@ -1948,6 +1954,7 @@
 		dev->has_remote = 1;
 		board_flyvideo(dev);
 		break;
+	case SAA7134_BOARD_FLYTVPLATINUM_FM:
 	case SAA7134_BOARD_CINERGY400:
 	case SAA7134_BOARD_CINERGY600:
 	case SAA7134_BOARD_CINERGY600_MK3:
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index dd4a6c8..c2873ae 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -172,7 +172,7 @@
 	return request_firmware(fw, name, &dev->pci->dev);
 }
 
-struct tda1004x_config medion_cardbus = {
+static struct tda1004x_config medion_cardbus = {
 	.demod_address = 0x08,  /* not sure this is correct */
 	.invert        = 0,
         .invert_oclk   = 0,
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 2021e09..fa13573 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -233,10 +233,7 @@
 		memset(f,0,sizeof(*f));
 		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-		/* FIXME: translate subsampling type EMPRESS into
-		 *        width/height: */
-		f->fmt.pix.width        = 720; /* D1 */
-		f->fmt.pix.height       = 576;
+		saa7134_i2c_call_clients(dev, cmd, arg);
 		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 		f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
 		return 0;
@@ -249,20 +246,7 @@
 		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		    return -EINVAL;
 
-		/*
-		  FIXME: translate and round width/height into EMPRESS
-		  subsample type:
-
-		          type  |   PAL   |  NTSC
-			---------------------------
-			  SIF   | 352x288 | 352x240
-			 1/2 D1 | 352x576 | 352x480
-			 2/3 D1 | 480x576 | 480x480
-			  D1    | 720x576 | 720x480
-		*/
-
-		f->fmt.pix.width        = 720; /* D1 */
-		f->fmt.pix.height       = 576;
+		saa7134_i2c_call_clients(dev, cmd, arg);
 		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 		f->fmt.pix.sizeimage    = TS_PACKET_SIZE* dev->ts.nr_packets;
 		return 0;
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 727d437..ca50cf5 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -379,6 +379,7 @@
 	switch (dev->board) {
 	case SAA7134_BOARD_FLYVIDEO2000:
 	case SAA7134_BOARD_FLYVIDEO3000:
+	case SAA7134_BOARD_FLYTVPLATINUM_FM:
 		ir_codes     = flyvideo_codes;
 		mask_keycode = 0xEC00000;
 		mask_keydown = 0x0040000;
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 881a053..6212388e 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -357,8 +357,16 @@
 		    V4L2_TUNER_RADIO != t->mode)
 			set_tv_freq(client,400*16);
 		t->mode  = f->type;
-		t->freq  = f->frequency;
-		set_freq(client,t->freq);
+		set_freq(client,f->frequency);
+		break;
+	}
+	case VIDIOC_G_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		SWITCH_V4L2;
+		f->type = t->mode;
+		f->frequency = t->freq;
 		break;
 	}
 	case VIDIOC_G_TUNER:
@@ -368,6 +376,8 @@
 		SWITCH_V4L2;
 		if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
 			tuner->signal = t->has_signal(client);
+		tuner->rangelow = tv_range[0] * 16;
+		tuner->rangehigh = tv_range[1] * 16;
 		break;
 	}
 	default:
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 065eb40..80dc34f 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -991,7 +991,7 @@
 {
 	if (tda9874a_SIF > 2)
 		tda9874a_SIF = 1;
-	if (tda9874a_STD >= 8)
+	if (tda9874a_STD > 8)
 		tda9874a_STD = 0;
 	if(tda9874a_AMSEL > 1)
 		tda9874a_AMSEL = 0;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 72f2b46..2e70d74 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -51,7 +51,7 @@
 
 config MMC_WBSD
 	tristate "Winbond W83L51xD SD/MMC Card Interface support"
-	depends on MMC && ISA
+	depends on MMC && ISA && ISA_DMA_API
 	help
 	  This selects the Winbond(R) W83L51xD Secure digital and
           Multimedia card Interface.
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 43e2ac5..b5e0760 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1581,7 +1581,8 @@
 
 	if (VORTEX_PCI(vp)) {
 		pci_set_power_state(VORTEX_PCI(vp), PCI_D0);	/* Go active */
-		pci_restore_state(VORTEX_PCI(vp));
+		if (vp->pm_state_valid)
+			pci_restore_state(VORTEX_PCI(vp));
 		pci_enable_device(VORTEX_PCI(vp));
 	}
 
@@ -2741,6 +2742,7 @@
 		outl(0, ioaddr + DownListPtr);
 
 	if (final_down && VORTEX_PCI(vp)) {
+		vp->pm_state_valid = 1;
 		pci_save_state(VORTEX_PCI(vp));
 		acpi_set_WOL(dev);
 	}
@@ -3243,9 +3245,10 @@
 		outw(RxEnable, ioaddr + EL3_CMD);
 
 		pci_enable_wake(VORTEX_PCI(vp), 0, 1);
+
+		/* Change the power state to D3; RxEnable doesn't take effect. */
+		pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
 	}
-	/* Change the power state to D3; RxEnable doesn't take effect. */
-	pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
 }
 
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 68242bd..3a0a55b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -589,7 +589,7 @@
 
 config ELPLUS
 	tristate "3c505 \"EtherLink Plus\" support"
-	depends on NET_VENDOR_3COM && ISA
+	depends on NET_VENDOR_3COM && ISA && ISA_DMA_API
 	---help---
 	  Information about this network (Ethernet) card can be found in
 	  <file:Documentation/networking/3c505.txt>.  If you have a card of
@@ -630,7 +630,7 @@
 
 config 3C515
 	tristate "3c515 ISA \"Fast EtherLink\""
-	depends on NET_VENDOR_3COM && (ISA || EISA)
+	depends on NET_VENDOR_3COM && (ISA || EISA) && ISA_DMA_API
 	help
 	  If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
 	  network card, say Y and read the Ethernet-HOWTO, available from
@@ -708,7 +708,7 @@
 
 config LANCE
 	tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
-	depends on NET_ETHERNET && ISA
+	depends on NET_ETHERNET && ISA && ISA_DMA_API
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -864,7 +864,7 @@
 
 config NI65
 	tristate "NI6510 support"
-	depends on NET_VENDOR_RACAL && ISA
+	depends on NET_VENDOR_RACAL && ISA && ISA_DMA_API
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -1072,7 +1072,7 @@
 
 config ZNET
 	tristate "Zenith Z-Note support (EXPERIMENTAL)"
-	depends on NET_ISA && EXPERIMENTAL
+	depends on NET_ISA && EXPERIMENTAL && ISA_DMA_API
 	help
 	  The Zenith Z-Note notebook computer has a built-in network
 	  (Ethernet) card, and this is the Linux driver for it. Note that the
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index fc51937..fb43332 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)Space.c	1.0.7	08/12/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Donald J. Becker, <becker@scyld.com>
  *
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index 60b1967..69c488d 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -13,7 +13,7 @@
 
 config LTPC
 	tristate "Apple/Farallon LocalTalk PC support"
-	depends on DEV_APPLETALK && (ISA || EISA)
+	depends on DEV_APPLETALK && (ISA || EISA) && ISA_DMA_API
 	help
 	  This allows you to use the AppleTalk PC card to connect to LocalTalk
 	  networks. The card is also known as the Farallon PhoneNet PC card.
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 2161c2d..9edaa18 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -65,7 +65,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
-#include <linux/if_ltalk.h>	/* For ltalk_setup() */
+#include <linux/if_ltalk.h>
 #include <linux/delay.h>	/* For udelay() */
 #include <linux/atalk.h>
 #include <linux/spinlock.h>
@@ -223,7 +223,7 @@
 	int base_addr;
 	int err = 0;
 
-	dev = alloc_netdev(sizeof(struct cops_local), "lt%d", ltalk_setup);
+	dev = alloc_ltalkdev(sizeof(struct cops_local));
 	if (!dev)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/drivers/net/appletalk/cops_ffdrv.h b/drivers/net/appletalk/cops_ffdrv.h
index 4131b4a..31cf8c9 100644
--- a/drivers/net/appletalk/cops_ffdrv.h
+++ b/drivers/net/appletalk/cops_ffdrv.h
@@ -28,7 +28,7 @@
 
 #ifdef CONFIG_COPS_DAYNA
 
-unsigned char ffdrv_code[] = {
+static const unsigned char ffdrv_code[] = {
 	58,3,0,50,228,149,33,255,255,34,226,149,
 	249,17,40,152,33,202,154,183,237,82,77,68,
 	11,107,98,19,54,0,237,176,175,50,80,0,
diff --git a/drivers/net/appletalk/cops_ltdrv.h b/drivers/net/appletalk/cops_ltdrv.h
index 05de66d..4afb8e1 100644
--- a/drivers/net/appletalk/cops_ltdrv.h
+++ b/drivers/net/appletalk/cops_ltdrv.h
@@ -27,7 +27,7 @@
 
 #ifdef CONFIG_COPS_TANGENT
 
-unsigned char ltdrv_code[] = {
+static const unsigned char ltdrv_code[] = {
 	58,3,0,50,148,10,33,143,15,62,85,119,
 	190,32,9,62,170,119,190,32,3,35,24,241,
 	34,146,10,249,17,150,10,33,143,15,183,237,
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index ad8e943..db4f369 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1039,7 +1039,7 @@
 	unsigned long f;
 	unsigned long timeout;
 
-	dev = alloc_netdev(sizeof(struct ltpc_private), "lt%d", ltalk_setup);
+	dev = alloc_ltalkdev(sizeof(struct ltpc_private));
 	if (!dev)
 		goto out;
 
diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c
index 16e155b..6648558 100644
--- a/drivers/net/arcnet/capmode.c
+++ b/drivers/net/arcnet/capmode.c
@@ -48,7 +48,7 @@
 static int ack_tx(struct net_device *dev, int acked);
 
 
-struct ArcProto capmode_proto =
+static struct ArcProto capmode_proto =
 {
 	'r',
 	XMTU,
diff --git a/drivers/net/gt96100eth.h b/drivers/net/gt96100eth.h
index 2f4bfd4..395869c 100644
--- a/drivers/net/gt96100eth.h
+++ b/drivers/net/gt96100eth.h
@@ -214,7 +214,7 @@
 	u32 cmdstat;
 	u32 next;
 	u32 buff_ptr;
-} gt96100_td_t __attribute__ ((packed));
+} __attribute__ ((packed)) gt96100_td_t;
 
 typedef struct {
 #ifdef DESC_BE
@@ -227,7 +227,7 @@
 	u32 cmdstat;
 	u32 next;
 	u32 buff_ptr;
-} gt96100_rd_t __attribute__ ((packed));
+} __attribute__ ((packed)) gt96100_rd_t;
 
 
 /* Values for the Tx command-status descriptor entry. */
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 067b353..8945491 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -394,13 +394,11 @@
 	if ((skb = dev_alloc_skb(count)) == NULL)
 		goto out_mem;
 
-	skb->dev = sp->dev;
 	ptr = skb_put(skb, count);
 	*ptr++ = cmd;	/* KISS command */
 
 	memcpy(ptr, sp->cooked_buf + 1, count);
-	skb->mac.raw = skb->data;
-	skb->protocol = htons(ETH_P_AX25);
+	skb->protocol = ax25_type_trans(skb, sp->dev);
 	netif_rx(skb);
 	sp->dev->last_rx = jiffies;
 	sp->stats.rx_packets++;
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 34068f8..7cdebe1 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -45,7 +45,7 @@
 
 config DMASCC
 	tristate "High-speed (DMA) SCC driver for AX.25"
-	depends on ISA && AX25 && BROKEN_ON_SMP
+	depends on ISA && AX25 && BROKEN_ON_SMP && ISA_DMA_API
 	---help---
 	  This is a driver for high-speed SCC boards, i.e. those supporting
 	  DMA on one port. You usually use those boards to connect your
@@ -78,7 +78,7 @@
 
 config SCC
 	tristate "Z8530 SCC driver"
-	depends on ISA && AX25
+	depends on ISA && AX25 && ISA_DMA_API
 	---help---
 	  These cards are used to connect your Linux box to an amateur radio
 	  in order to communicate with other computers. If you want to use
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index e8cb87d..1c563f9 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -601,12 +601,10 @@
 		bc->stats.rx_dropped++;
 		return;
 	}
-	skb->dev = dev;
 	cp = skb_put(skb, pktlen);
 	*cp++ = 0; /* KISS kludge */
 	memcpy(cp, bc->hdlcrx.buf, pktlen - 1);
-	skb->protocol = htons(ETH_P_AX25);
-	skb->mac.raw = skb->data;
+	skb->protocol = ax25_type_trans(skb, dev);
 	netif_rx(skb);
 	dev->last_rx = jiffies;
 	bc->stats.rx_packets++;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index ef1a359..ba9f058 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -211,11 +211,7 @@
 	ptr = skb_push(skb, 1);
 	*ptr = 0;
 
-	skb->dev = dev;
-	skb->protocol = htons(ETH_P_AX25);
-	skb->mac.raw = skb->data;
-	skb->pkt_type = PACKET_HOST;
-
+	skb->protocol = ax25_type_trans(skb, dev);
 	netif_rx(skb);
 	dev->last_rx = jiffies;
 unlock:
@@ -272,8 +268,6 @@
 		skb = newskb;
 	}
 
-	skb->protocol = htons(ETH_P_AX25);
-
 	ptr = skb_push(skb, 2);
 
 	*ptr++ = (size + 5) % 256;
@@ -287,7 +281,7 @@
 		return -ENODEV;
 	}
 
-	skb->dev = dev;
+	skb->protocol = ax25_type_trans(skb, dev);
 	skb->nh.raw = skb->data;
 	dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
 	bpq->stats.tx_packets++;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index f3269b7..f515245 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -1306,9 +1306,7 @@
 			data = skb_put(skb, cb + 1);
 			data[0] = 0;
 			memcpy(&data[1], priv->rx_buf[i], cb);
-			skb->dev = priv->dev;
-			skb->protocol = ntohs(ETH_P_AX25);
-			skb->mac.raw = skb->data;
+			skb->protocol = ax25_type_trans(skb, priv->dev);
 			netif_rx(skb);
 			priv->dev->last_rx = jiffies;
 			priv->stats.rx_packets++;
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b89959a..b4c836e 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -174,12 +174,10 @@
 		s->stats.rx_dropped++;
 		return;
 	}
-	skb->dev = dev;
 	cp = skb_put(skb, pkt_len);
 	*cp++ = 0; /* KISS kludge */
 	memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
-	skb->protocol = htons(ETH_P_AX25);
-	skb->mac.raw = skb->data;
+	skb->protocol = ax25_type_trans(skb, dev);
 	netif_rx(skb);
 	dev->last_rx = jiffies;
 	s->stats.rx_packets++;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d9ea080..6279051 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -332,12 +332,10 @@
 		return;
 	}
 
-	skb->dev      = ax->dev;
 	spin_lock_bh(&ax->buflock);
 	memcpy(skb_put(skb,count), ax->rbuff, count);
 	spin_unlock_bh(&ax->buflock);
-	skb->mac.raw  = skb->data;
-	skb->protocol = htons(ETH_P_AX25);
+	skb->protocol = ax25_type_trans(skb, ax->dev);
 	netif_rx(skb);
 	ax->dev->last_rx = jiffies;
 	ax->rx_packets++;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index ce9e7af..ece1b1a 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1630,10 +1630,7 @@
 	scc->dev_stat.rx_packets++;
 	scc->dev_stat.rx_bytes += skb->len;
 
-	skb->dev      = scc->dev;
-	skb->protocol = htons(ETH_P_AX25);
-	skb->mac.raw  = skb->data;
-	skb->pkt_type = PACKET_HOST;
+	skb->protocol = ax25_type_trans(skb, scc->dev);
 	
 	netif_rx(skb);
 	scc->dev->last_rx = jiffies;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index fd7b00f..41213ef 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -522,12 +522,10 @@
 				++yp->stats.rx_dropped;
 			} else {
 				unsigned char *cp;
-				skb->dev = dev;
 				cp = skb_put(skb, pkt_len);
 				*cp++ = 0;		/* KISS kludge */
 				memcpy(cp, yp->rx_buf, pkt_len - 1);
-				skb->protocol = htons(ETH_P_AX25);
-				skb->mac.raw = skb->data;
+				skb->protocol = ax25_type_trans(skb, dev);
 				netif_rx(skb);
 				dev->last_rx = jiffies;
 				++yp->stats.rx_packets;
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index acb1701..b3a898c 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -13,8 +13,8 @@
 ** This driver has only been tested with
 ** -- HP J2585B 10/100 Mbit/s PCI Busmaster
 ** -- HP J2585A 10/100 Mbit/s PCI 
-** -- HP J2970  10 Mbit/s PCI Combo 10base-T/BNC
-** -- HP J2973  10 Mbit/s PCI 10base-T
+** -- HP J2970A 10 Mbit/s PCI Combo 10base-T/BNC
+** -- HP J2973A 10 Mbit/s PCI 10base-T
 ** -- HP J2573  10/100 ISA
 ** -- Compex ReadyLink ENET100-VG4  10/100 Mbit/s PCI / EISA
 ** -- Compex FreedomLine 100/VG  10/100 Mbit/s ISA / EISA / PCI
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 6bf76a4..1c553d7 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -310,7 +310,7 @@
 
 config NSC_FIR
 	tristate "NSC PC87108/PC87338"
-	depends on IRDA
+	depends on IRDA && ISA_DMA_API
 	help
 	  Say Y here if you want to build support for the NSC PC87108 and
 	  PC87338 IrDA chipsets.  This driver supports SIR,
@@ -321,7 +321,7 @@
 
 config WINBOND_FIR
 	tristate "Winbond W83977AF (IR)"
-	depends on IRDA
+	depends on IRDA && ISA_DMA_API
 	help
 	  Say Y here if you want to build IrDA support for the Winbond
 	  W83977AF super-io chipset.  This driver should be used for the IrDA
@@ -347,7 +347,7 @@
 
 config SMC_IRCC_FIR
 	tristate "SMSC IrCC (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && IRDA
+	depends on EXPERIMENTAL && IRDA && ISA_DMA_API
 	help
 	  Say Y here if you want to build support for the SMC Infrared
 	  Communications Controller.  It is used in a wide variety of
@@ -357,7 +357,7 @@
 
 config ALI_FIR
 	tristate "ALi M5123 FIR (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && IRDA
+	depends on EXPERIMENTAL && IRDA && ISA_DMA_API
 	help
 	  Say Y here if you want to build support for the ALi M5123 FIR
 	  Controller.  The ALi M5123 FIR Controller is embedded in ALi M1543C,
@@ -385,7 +385,7 @@
 
 config VIA_FIR
 	tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
-	depends on IRDA
+	depends on IRDA && ISA_DMA_API
 	help
 	  Say Y here if you want to build support for the VIA VT8231
 	  and VIA VT1211 IrDA controllers, found on the motherboards using
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 2ffc317..b33111e 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)loopback.c	1.0.4b	08/16/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Donald Becker, <becker@scyld.com>
  *
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 7e94d45..0405e1f 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -99,7 +99,7 @@
 
 static inline u32 mv_read(int offset)
 {
-	void *__iomem reg_base;
+	void __iomem *reg_base;
 
 	reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
 
@@ -108,7 +108,7 @@
 
 static inline void mv_write(int offset, u32 data)
 {
-	void * __iomem reg_base;
+	void __iomem *reg_base;
 
 	reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
 	writel(data, reg_base + offset);
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
index 507d632..3872088 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp_deflate.c
@@ -87,8 +87,7 @@
 
 	if (state) {
 		zlib_deflateEnd(&state->strm);
-		if (state->strm.workspace)
-			vfree(state->strm.workspace);
+		vfree(state->strm.workspace);
 		kfree(state);
 	}
 }
@@ -308,8 +307,7 @@
 
 	if (state) {
 		zlib_inflateEnd(&state->strm);
-		if (state->strm.workspace)
-			kfree(state->strm.workspace);
+		kfree(state->strm.workspace);
 		kfree(state);
 	}
 }
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index c456dc8..3b377f6 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -2467,14 +2467,10 @@
 	skb_queue_purge(&ppp->mrq);
 #endif /* CONFIG_PPP_MULTILINK */
 #ifdef CONFIG_PPP_FILTER
-	if (ppp->pass_filter) {
-		kfree(ppp->pass_filter);
-		ppp->pass_filter = NULL;
-	}
-	if (ppp->active_filter) {
-		kfree(ppp->active_filter);
-		ppp->active_filter = NULL;
-	}
+	kfree(ppp->pass_filter);
+	ppp->pass_filter = NULL;
+	kfree(ppp->active_filter);
+	ppp->active_filter = NULL;
 #endif /* CONFIG_PPP_FILTER */
 
 	kfree(ppp);
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 07e2df0..c59507f 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -2385,7 +2385,7 @@
 	}
 
 	/* Give a racing hard_start_xmit a few cycles to complete. */
-	synchronize_kernel();
+	synchronize_sched();  /* FIXME: should this be synchronize_irq()? */
 
 	/*
 	 * And now for the 50k$ question: are IRQ disabled or not ?
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 4ce52f5..8f7841c 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -185,15 +185,12 @@
 	/* Cleanup */
 err_exit:
 #ifdef SL_INCLUDE_CSLIP
-	if (cbuff)
-		kfree(cbuff);
+	kfree(cbuff);
 	if (slcomp)
 		slhc_free(slcomp);
 #endif
-	if (xbuff)
-		kfree(xbuff);
-	if (rbuff)
-		kfree(rbuff);
+	kfree(xbuff);
+	kfree(rbuff);
 	return err;
 }
 
@@ -204,13 +201,13 @@
 	void * tmp;
 
 	/* Free all SLIP frame buffers. */
-	if ((tmp = xchg(&sl->rbuff, NULL)) != NULL)
-		kfree(tmp);
-	if ((tmp = xchg(&sl->xbuff, NULL)) != NULL)
-		kfree(tmp);
+	tmp = xchg(&sl->rbuff, NULL);
+	kfree(tmp);
+	tmp = xchg(&sl->xbuff, NULL);
+	kfree(tmp);
 #ifdef SL_INCLUDE_CSLIP
-	if ((tmp = xchg(&sl->cbuff, NULL)) != NULL)
-		kfree(tmp);
+	tmp = xchg(&sl->cbuff, NULL);
+	kfree(tmp);
 	if ((tmp = xchg(&sl->slcomp, NULL)) != NULL)
 		slhc_free(tmp);
 #endif
@@ -297,13 +294,10 @@
 	spin_unlock_bh(&sl->lock);
 
 done:
-	if (xbuff)
-		kfree(xbuff);
-	if (rbuff)
-		kfree(rbuff);
+	kfree(xbuff);
+	kfree(rbuff);
 #ifdef SL_INCLUDE_CSLIP
-	if (cbuff)
-		kfree(cbuff);
+	kfree(cbuff);
 #endif
 	return err;
 }
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 025dcd8..f88f5e3 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -37,8 +37,18 @@
 
 #include "sunbmac.h"
 
+#define DRV_NAME	"sunbmac"
+#define DRV_VERSION	"2.0"
+#define DRV_RELDATE	"11/24/03"
+#define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
+
 static char version[] __initdata =
-        "sunbmac.c:v2.0 24/Nov/03 David S. Miller (davem@redhat.com)\n";
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION("Sun BigMAC 100baseT ethernet driver");
+MODULE_LICENSE("GPL");
 
 #undef DEBUG_PROBE
 #undef DEBUG_TX
@@ -1321,4 +1331,3 @@
 
 module_init(bigmac_probe);
 module_exit(bigmac_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index d837b3c..f02fe41 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -13,9 +13,6 @@
  *     argument : macaddr=0x00,0x10,0x20,0x30,0x40,0x50
  */
 
-static char version[] =
-        "sunhme.c:v2.02 24/Aug/2003 David S. Miller (davem@redhat.com)\n";
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -67,15 +64,24 @@
 
 #include "sunhme.h"
 
+#define DRV_NAME	"sunhme"
+#define DRV_VERSION	"2.02"
+#define DRV_RELDATE	"8/24/03"
+#define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
 
-#define DRV_NAME "sunhme"
+static char version[] =
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION("Sun HappyMealEthernet(HME) 10/100baseT ethernet driver");
+MODULE_LICENSE("GPL");
 
 static int macaddr[6];
 
 /* accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */
 module_param_array(macaddr, int, NULL, 0);
 MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set");
-MODULE_LICENSE("GPL");
 
 static struct happy_meal *root_happy_dev;
 
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 62d464c..b7d87d4 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -69,9 +69,6 @@
 
 #undef DEBUG_DRIVER
 
-static char version[] =
-	"sunlance.c:v2.02 24/Aug/03 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
-
 static char lancestr[] = "LANCE";
 
 #include <linux/config.h>
@@ -108,6 +105,19 @@
 #include <asm/auxio.h>		/* For tpe-link-test? setting */
 #include <asm/irq.h>
 
+#define DRV_NAME	"sunlance"
+#define DRV_VERSION	"2.02"
+#define DRV_RELDATE	"8/24/03"
+#define DRV_AUTHOR	"Miguel de Icaza (miguel@nuclecu.unam.mx)"
+
+static char version[] =
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION("Sun Lance ethernet driver");
+MODULE_LICENSE("GPL");
+
 /* Define: 2^4 Tx buffers and 2^4 Rx buffers */
 #ifndef LANCE_LOG_TX_BUFFERS
 #define LANCE_LOG_TX_BUFFERS 4
@@ -1611,4 +1621,3 @@
 
 module_init(sparc_lance_probe);
 module_exit(sparc_lance_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 37ef1b8..1f2323b 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -7,9 +7,6 @@
  * Copyright (C) 1996, 1999, 2003 David S. Miller (davem@redhat.com)
  */
 
-static char version[] =
-        "sunqe.c:v3.0 8/24/03 David S. Miller (davem@redhat.com)\n";
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -43,6 +40,19 @@
 
 #include "sunqe.h"
 
+#define DRV_NAME	"sunqe"
+#define DRV_VERSION	"3.0"
+#define DRV_RELDATE	"8/24/03"
+#define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
+
+static char version[] =
+	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION("Sun QuadEthernet 10baseT SBUS card driver");
+MODULE_LICENSE("GPL");
+
 static struct sunqec *root_qec_dev;
 
 static void qe_set_multicast(struct net_device *dev);
@@ -1040,4 +1050,3 @@
 
 module_init(qec_probe);
 module_exit(qec_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 12de808..f79b02e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -61,8 +61,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.25"
-#define DRV_MODULE_RELDATE	"March 24, 2005"
+#define DRV_MODULE_VERSION	"3.27"
+#define DRV_MODULE_RELDATE	"May 5, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -85,8 +85,7 @@
 /* hardware minimum and maximum for a single frame's data payload */
 #define TG3_MIN_MTU			60
 #define TG3_MAX_MTU(tp)	\
-	((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && \
-	  GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ? 9000 : 1500)
+	(!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 9000 : 1500)
 
 /* These numbers seem to be hard coded in the NIC firmware somehow.
  * You can't change the ring sizes, but you can change where you place
@@ -205,6 +204,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M,
@@ -425,9 +426,30 @@
 	tg3_cond_int(tp);
 }
 
+static inline unsigned int tg3_has_work(struct tg3 *tp)
+{
+	struct tg3_hw_status *sblk = tp->hw_status;
+	unsigned int work_exists = 0;
+
+	/* check for phy events */
+	if (!(tp->tg3_flags &
+	      (TG3_FLAG_USE_LINKCHG_REG |
+	       TG3_FLAG_POLL_SERDES))) {
+		if (sblk->status & SD_STATUS_LINK_CHG)
+			work_exists = 1;
+	}
+	/* check for RX/TX work to do */
+	if (sblk->idx[0].tx_consumer != tp->tx_cons ||
+	    sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
+		work_exists = 1;
+
+	return work_exists;
+}
+
 /* tg3_restart_ints
- *  similar to tg3_enable_ints, but it can return without flushing the
- *  PIO write which reenables interrupts
+ *  similar to tg3_enable_ints, but it accurately determines whether there
+ *  is new work pending and can return without flushing the PIO write
+ *  which reenables interrupts 
  */
 static void tg3_restart_ints(struct tg3 *tp)
 {
@@ -436,7 +458,9 @@
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
 	mmiowb();
 
-	tg3_cond_int(tp);
+	if (tg3_has_work(tp))
+		tw32(HOSTCC_MODE, tp->coalesce_mode |
+		     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
 }
 
 static inline void tg3_netif_stop(struct tg3 *tp)
@@ -860,8 +884,7 @@
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 		/* Cannot do read-modify-write on 5401 */
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
-	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-		   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+	} else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		u32 phy_reg;
 
 		/* Set bit 14 with read-modify-write to preserve other bits */
@@ -873,8 +896,7 @@
 	/* Set phy register 0x10 bit 0 to high fifo elasticity to support
 	 * jumbo frames transmission.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		u32 phy_reg;
 
 		if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg))
@@ -1006,8 +1028,13 @@
 		pci_write_config_word(tp->pdev,
 				      pm + PCI_PM_CTRL,
 				      power_control);
-		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-		udelay(100);
+		udelay(100);	/* Delay after power state change */
+
+		/* Switch out of Vaux if it is not a LOM */
+		if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) {
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+			udelay(100);
+		}
 
 		return 0;
 
@@ -1068,7 +1095,7 @@
 			mac_mode = MAC_MODE_PORT_MODE_TBI;
 		}
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
+		if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
 			tw32(MAC_LED_CTRL, tp->led_ctrl);
 
 		if (((power_caps & PCI_PM_CAP_PME_D3cold) &&
@@ -1095,7 +1122,7 @@
 		     CLOCK_CTRL_ALTCLK |
 		     CLOCK_CTRL_PWRDOWN_PLL133);
 		udelay(40);
-	} else if (!((GET_ASIC_REV(tp->pci_chip_rev_id) == 5750) &&
+	} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
 		     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
 		u32 newbits1, newbits2;
 
@@ -1152,6 +1179,7 @@
 
 	/* Finally, set the new power state. */
 	pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
+	udelay(100);	/* Delay after power state change */
 
 	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
@@ -2681,8 +2709,8 @@
 static int tg3_rx(struct tg3 *tp, int budget)
 {
 	u32 work_mask;
-	u32 rx_rcb_ptr = tp->rx_rcb_ptr;
-	u16 hw_idx, sw_idx;
+	u32 sw_idx = tp->rx_rcb_ptr;
+	u16 hw_idx;
 	int received;
 
 	hw_idx = tp->hw_status->idx[0].rx_producer;
@@ -2691,7 +2719,6 @@
 	 * the opaque cookie.
 	 */
 	rmb();
-	sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp);
 	work_mask = 0;
 	received = 0;
 	while (sw_idx != hw_idx && budget > 0) {
@@ -2796,14 +2823,19 @@
 next_pkt:
 		(*post_ptr)++;
 next_pkt_nopost:
-		rx_rcb_ptr++;
-		sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp);
+		sw_idx++;
+		sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
+
+		/* Refresh hw_idx to see if there is new work */
+		if (sw_idx == hw_idx) {
+			hw_idx = tp->hw_status->idx[0].rx_producer;
+			rmb();
+		}
 	}
 
 	/* ACK the status ring. */
-	tp->rx_rcb_ptr = rx_rcb_ptr;
-	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
-		     (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp)));
+	tp->rx_rcb_ptr = sw_idx;
+	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, sw_idx);
 
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
@@ -2882,24 +2914,41 @@
 	return (done ? 0 : 1);
 }
 
-static inline unsigned int tg3_has_work(struct net_device *dev, struct tg3 *tp)
+/* MSI ISR - No need to check for interrupt sharing and no need to
+ * flush status block and interrupt mailbox. PCI ordering rules
+ * guarantee that MSI will arrive after the status block.
+ */
+static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct net_device *dev = dev_id;
+	struct tg3 *tp = netdev_priv(dev);
 	struct tg3_hw_status *sblk = tp->hw_status;
-	unsigned int work_exists = 0;
+	unsigned long flags;
 
-	/* check for phy events */
-	if (!(tp->tg3_flags &
-	      (TG3_FLAG_USE_LINKCHG_REG |
-	       TG3_FLAG_POLL_SERDES))) {
-		if (sblk->status & SD_STATUS_LINK_CHG)
-			work_exists = 1;
+	spin_lock_irqsave(&tp->lock, flags);
+
+	/*
+	 * writing any value to intr-mbox-0 clears PCI INTA# and
+	 * chip-internal interrupt pending events.
+	 * writing non-zero to intr-mbox-0 additional tells the
+	 * NIC to stop sending us irqs, engaging "in-intr-handler"
+	 * event coalescing.
+	 */
+	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+	sblk->status &= ~SD_STATUS_UPDATED;
+
+	if (likely(tg3_has_work(tp)))
+		netif_rx_schedule(dev);		/* schedule NAPI poll */
+	else {
+		/* no work, re-enable interrupts
+		 */
+		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+			     0x00000000);
 	}
-	/* check for RX/TX work to do */
-	if (sblk->idx[0].tx_consumer != tp->tx_cons ||
-	    sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
-		work_exists = 1;
 
-	return work_exists;
+	spin_unlock_irqrestore(&tp->lock, flags);
+
+	return IRQ_RETVAL(1);
 }
 
 static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -2935,7 +2984,7 @@
 		tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 		sblk->status &= ~SD_STATUS_UPDATED;
 
-		if (likely(tg3_has_work(dev, tp)))
+		if (likely(tg3_has_work(tp)))
 			netif_rx_schedule(dev);		/* schedule NAPI poll */
 		else {
 			/* no work, shared interrupt perhaps?  re-enable
@@ -2954,13 +3003,31 @@
 	return IRQ_RETVAL(handled);
 }
 
+/* ISR for interrupt test */
+static irqreturn_t tg3_test_isr(int irq, void *dev_id,
+		struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct tg3 *tp = netdev_priv(dev);
+	struct tg3_hw_status *sblk = tp->hw_status;
+
+	if (sblk->status & SD_STATUS_UPDATED) {
+		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+			     0x00000001);
+		return IRQ_RETVAL(1);
+	}
+	return IRQ_RETVAL(0);
+}
+
 static int tg3_init_hw(struct tg3 *);
-static int tg3_halt(struct tg3 *);
+static int tg3_halt(struct tg3 *, int);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void tg3_poll_controller(struct net_device *dev)
 {
-	tg3_interrupt(dev->irq, dev, NULL);
+	struct tg3 *tp = netdev_priv(dev);
+
+	tg3_interrupt(tp->pdev->irq, dev, NULL);
 }
 #endif
 
@@ -2977,7 +3044,7 @@
 	restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
 	tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
 
-	tg3_halt(tp);
+	tg3_halt(tp, 0);
 	tg3_init_hw(tp);
 
 	tg3_netif_start(tp);
@@ -3323,7 +3390,7 @@
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
-	tg3_halt(tp);
+	tg3_halt(tp, 1);
 
 	tg3_set_mtu(dev, tp, new_mtu);
 
@@ -3590,7 +3657,7 @@
 /* To stop a block, clear the enable bit and poll till it
  * clears.  tp->lock is held.
  */
-static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit)
+static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int silent)
 {
 	unsigned int i;
 	u32 val;
@@ -3623,7 +3690,7 @@
 			break;
 	}
 
-	if (i == MAX_WAIT_CNT) {
+	if (i == MAX_WAIT_CNT && !silent) {
 		printk(KERN_ERR PFX "tg3_stop_block timed out, "
 		       "ofs=%lx enable_bit=%x\n",
 		       ofs, enable_bit);
@@ -3634,7 +3701,7 @@
 }
 
 /* tp->lock is held. */
-static int tg3_abort_hw(struct tg3 *tp)
+static int tg3_abort_hw(struct tg3 *tp, int silent)
 {
 	int i, err;
 
@@ -3644,22 +3711,20 @@
 	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
-	err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
-	err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE);
-	err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE);
+	err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE, silent);
 
-	err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE);
-	err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE);
-	err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
-	err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE);
-	if (err)
-		goto out;
+	err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE, silent);
 
 	tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
 	tw32_f(MAC_MODE, tp->mac_mode);
@@ -3677,27 +3742,24 @@
 		printk(KERN_ERR PFX "tg3_abort_hw timed out for %s, "
 		       "TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n",
 		       tp->dev->name, tr32(MAC_TX_MODE));
-		return -ENODEV;
+		err |= -ENODEV;
 	}
 
-	err  = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE);
-	err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
+	err |= tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE, silent);
 
 	tw32(FTQ_RESET, 0xffffffff);
 	tw32(FTQ_RESET, 0x00000000);
 
-	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
-	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
-	if (err)
-		goto out;
+	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent);
+	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent);
 
 	if (tp->hw_status)
 		memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
 	if (tp->hw_stats)
 		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
-out:
 	return err;
 }
 
@@ -3727,6 +3789,28 @@
 }
 
 /* tp->lock is held. */
+static void tg3_enable_nvram_access(struct tg3 *tp)
+{
+	if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) {
+		u32 nvaccess = tr32(NVRAM_ACCESS);
+
+		tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+	}
+}
+
+/* tp->lock is held. */
+static void tg3_disable_nvram_access(struct tg3 *tp)
+{
+	if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM)) {
+		u32 nvaccess = tr32(NVRAM_ACCESS);
+
+		tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+	}
+}
+
+/* tp->lock is held. */
 static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
 {
 	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
@@ -3967,7 +4051,7 @@
 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
 		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
 			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+			if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
 				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
 		}
 	}
@@ -3997,7 +4081,7 @@
 }
 
 /* tp->lock is held. */
-static int tg3_halt(struct tg3 *tp)
+static int tg3_halt(struct tg3 *tp, int silent)
 {
 	int err;
 
@@ -4005,7 +4089,7 @@
 
 	tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN);
 
-	tg3_abort_hw(tp);
+	tg3_abort_hw(tp, silent);
 	err = tg3_chip_reset(tp);
 
 	tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN);
@@ -4974,9 +5058,7 @@
 	tg3_write_sig_pre_reset(tp, RESET_KIND_INIT);
 
 	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-		err = tg3_abort_hw(tp);
-		if (err)
-			return err;
+		tg3_abort_hw(tp, 1);
 	}
 
 	err = tg3_chip_reset(tp);
@@ -5041,7 +5123,7 @@
 	tw32(GRC_MISC_CFG, val);
 
 	/* Initialize MBUF/DESC pool. */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
 		/* Do nothing.  */
 	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
 		tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
@@ -5238,6 +5320,8 @@
 		      RDMAC_MODE_LNGREAD_ENAB);
 	if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
 		rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
+
+	/* If statement applies to 5705 and 5750 PCI devices only */
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
 	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
@@ -5251,6 +5335,9 @@
 		}
 	}
 
+	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+		rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+
 #if TG3_TSO_SUPPORT != 0
 	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		rdmac_mode |= (1 << 27);
@@ -5332,10 +5419,28 @@
 	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
 	udelay(40);
 
-	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+	/* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
+	 * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the
+	 * register to preserve the GPIO settings for LOMs. The GPIOs,
+	 * whether used as inputs or outputs, are set by boot code after
+	 * reset.
+	 */
+	if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
+		u32 gpio_mask;
+
+		gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 |
+			    GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2;
+
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+			gpio_mask |= GRC_LCLCTRL_GPIO_OE3 |
+				     GRC_LCLCTRL_GPIO_OUTPUT3;
+
+		tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
+
+		/* GPIO1 must be driven high for eeprom write protect */
 		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
 				       GRC_LCLCTRL_GPIO_OUTPUT1);
+	}
 	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
@@ -5353,6 +5458,7 @@
 	       WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
 	       WDMAC_MODE_LNGREAD_ENAB);
 
+	/* If statement applies to 5705 and 5750 PCI devices only */
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
 	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
@@ -5706,6 +5812,118 @@
 	add_timer(&tp->timer);
 }
 
+static int tg3_test_interrupt(struct tg3 *tp)
+{
+	struct net_device *dev = tp->dev;
+	int err, i;
+	u32 int_mbox = 0;
+
+	tg3_disable_ints(tp);
+
+	free_irq(tp->pdev->irq, dev);
+
+	err = request_irq(tp->pdev->irq, tg3_test_isr,
+			  SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+	if (err)
+		return err;
+
+	tg3_enable_ints(tp);
+
+	tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
+	       HOSTCC_MODE_NOW);
+
+	for (i = 0; i < 5; i++) {
+		int_mbox = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+		if (int_mbox != 0)
+			break;
+		msleep(10);
+	}
+
+	tg3_disable_ints(tp);
+
+	free_irq(tp->pdev->irq, dev);
+	
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
+		err = request_irq(tp->pdev->irq, tg3_msi,
+				  SA_SAMPLE_RANDOM, dev->name, dev);
+	else
+		err = request_irq(tp->pdev->irq, tg3_interrupt,
+				  SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+
+	if (err)
+		return err;
+
+	if (int_mbox != 0)
+		return 0;
+
+	return -EIO;
+}
+
+/* Returns 0 if MSI test succeeds or MSI test fails and INTx mode is
+ * successfully restored
+ */
+static int tg3_test_msi(struct tg3 *tp)
+{
+	struct net_device *dev = tp->dev;
+	int err;
+	u16 pci_cmd;
+
+	if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSI))
+		return 0;
+
+	/* Turn off SERR reporting in case MSI terminates with Master
+	 * Abort.
+	 */
+	pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
+	pci_write_config_word(tp->pdev, PCI_COMMAND,
+			      pci_cmd & ~PCI_COMMAND_SERR);
+
+	err = tg3_test_interrupt(tp);
+
+	pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
+
+	if (!err)
+		return 0;
+
+	/* other failures */
+	if (err != -EIO)
+		return err;
+
+	/* MSI test failed, go back to INTx mode */
+	printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
+	       "switching to INTx mode. Please report this failure to "
+	       "the PCI maintainer and include system chipset information.\n",
+		       tp->dev->name);
+
+	free_irq(tp->pdev->irq, dev);
+	pci_disable_msi(tp->pdev);
+
+	tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
+
+	err = request_irq(tp->pdev->irq, tg3_interrupt,
+			  SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+
+	if (err)
+		return err;
+
+	/* Need to reset the chip because the MSI cycle may have terminated
+	 * with Master Abort.
+	 */
+	spin_lock_irq(&tp->lock);
+	spin_lock(&tp->tx_lock);
+
+	tg3_halt(tp, 1);
+	err = tg3_init_hw(tp);
+
+	spin_unlock(&tp->tx_lock);
+	spin_unlock_irq(&tp->lock);
+
+	if (err)
+		free_irq(tp->pdev->irq, dev);
+
+	return err;
+}
+
 static int tg3_open(struct net_device *dev)
 {
 	struct tg3 *tp = netdev_priv(dev);
@@ -5727,10 +5945,29 @@
 	if (err)
 		return err;
 
-	err = request_irq(dev->irq, tg3_interrupt,
-			  SA_SHIRQ, dev->name, dev);
+	if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
+	    (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
+	    (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) {
+		if (pci_enable_msi(tp->pdev) == 0) {
+			u32 msi_mode;
+
+			msi_mode = tr32(MSGINT_MODE);
+			tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
+			tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
+		}
+	}
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
+		err = request_irq(tp->pdev->irq, tg3_msi,
+				  SA_SAMPLE_RANDOM, dev->name, dev);
+	else
+		err = request_irq(tp->pdev->irq, tg3_interrupt,
+				  SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
 
 	if (err) {
+		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+			pci_disable_msi(tp->pdev);
+			tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
+		}
 		tg3_free_consistent(tp);
 		return err;
 	}
@@ -5740,7 +5977,7 @@
 
 	err = tg3_init_hw(tp);
 	if (err) {
-		tg3_halt(tp);
+		tg3_halt(tp, 1);
 		tg3_free_rings(tp);
 	} else {
 		tp->timer_offset = HZ / 10;
@@ -5751,23 +5988,47 @@
 		tp->timer.expires = jiffies + tp->timer_offset;
 		tp->timer.data = (unsigned long) tp;
 		tp->timer.function = tg3_timer;
-		add_timer(&tp->timer);
-
-		tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
 	}
 
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
 	if (err) {
-		free_irq(dev->irq, dev);
+		free_irq(tp->pdev->irq, dev);
+		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+			pci_disable_msi(tp->pdev);
+			tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
+		}
 		tg3_free_consistent(tp);
 		return err;
 	}
 
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+		err = tg3_test_msi(tp);
+		if (err) {
+			spin_lock_irq(&tp->lock);
+			spin_lock(&tp->tx_lock);
+
+			if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+				pci_disable_msi(tp->pdev);
+				tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
+			}
+			tg3_halt(tp, 1);
+			tg3_free_rings(tp);
+			tg3_free_consistent(tp);
+
+			spin_unlock(&tp->tx_lock);
+			spin_unlock_irq(&tp->lock);
+
+			return err;
+		}
+	}
+
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
+	add_timer(&tp->timer);
+	tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
 	tg3_enable_ints(tp);
 
 	spin_unlock(&tp->tx_lock);
@@ -6025,7 +6286,7 @@
 
 	tg3_disable_ints(tp);
 
-	tg3_halt(tp);
+	tg3_halt(tp, 1);
 	tg3_free_rings(tp);
 	tp->tg3_flags &=
 		~(TG3_FLAG_INIT_COMPLETE |
@@ -6035,7 +6296,11 @@
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	free_irq(dev->irq, dev);
+	free_irq(tp->pdev->irq, dev);
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+		pci_disable_msi(tp->pdev);
+		tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
+	}
 
 	memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev),
 	       sizeof(tp->net_stats_prev));
@@ -6509,10 +6774,12 @@
 		start = cpu_to_le32(start);
 		len += b_offset;
 		offset &= ~3;
+		if (len < 4)
+			len = 4;
 	}
 
 	odd_len = 0;
-	if ((len & 3) && ((len > 4) || (b_offset == 0))) {
+	if (len & 3) {
 		/* adjustments to end on required 4 byte boundary */
 		odd_len = 1;
 		len = (len + 3) & ~3;
@@ -6739,7 +7006,7 @@
 	tp->tx_pending = ering->tx_pending;
 
 	if (netif_running(dev)) {
-		tg3_halt(tp);
+		tg3_halt(tp, 1);
 		tg3_init_hw(tp);
 		tg3_netif_start(tp);
 	}
@@ -6782,7 +7049,7 @@
 		tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
 
 	if (netif_running(dev)) {
-		tg3_halt(tp);
+		tg3_halt(tp, 1);
 		tg3_init_hw(tp);
 		tg3_netif_start(tp);
 	}
@@ -7067,6 +7334,67 @@
 	}
 }
 
+static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
+{
+	u32 nvcfg1;
+
+	nvcfg1 = tr32(NVRAM_CFG1);
+
+	/* NVRAM protection for TPM */
+	if (nvcfg1 & (1 << 27))
+		tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+
+	switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+		case FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ:
+		case FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ:
+			tp->nvram_jedecnum = JEDEC_ATMEL;
+			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+			break;
+		case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+			tp->nvram_jedecnum = JEDEC_ATMEL;
+			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+			tp->tg3_flags2 |= TG3_FLG2_FLASH;
+			break;
+		case FLASH_5752VENDOR_ST_M45PE10:
+		case FLASH_5752VENDOR_ST_M45PE20:
+		case FLASH_5752VENDOR_ST_M45PE40:
+			tp->nvram_jedecnum = JEDEC_ST;
+			tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+			tp->tg3_flags2 |= TG3_FLG2_FLASH;
+			break;
+	}
+
+	if (tp->tg3_flags2 & TG3_FLG2_FLASH) {
+		switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+			case FLASH_5752PAGE_SIZE_256:
+				tp->nvram_pagesize = 256;
+				break;
+			case FLASH_5752PAGE_SIZE_512:
+				tp->nvram_pagesize = 512;
+				break;
+			case FLASH_5752PAGE_SIZE_1K:
+				tp->nvram_pagesize = 1024;
+				break;
+			case FLASH_5752PAGE_SIZE_2K:
+				tp->nvram_pagesize = 2048;
+				break;
+			case FLASH_5752PAGE_SIZE_4K:
+				tp->nvram_pagesize = 4096;
+				break;
+			case FLASH_5752PAGE_SIZE_264:
+				tp->nvram_pagesize = 264;
+				break;
+		}
+	}
+	else {
+		/* For eeprom, set pagesize to maximum eeprom size */
+		tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+		nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+		tw32(NVRAM_CFG1, nvcfg1);
+	}
+}
+
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
 static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
@@ -7093,20 +7421,16 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
 		tp->tg3_flags |= TG3_FLAG_NVRAM;
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-			u32 nvaccess = tr32(NVRAM_ACCESS);
+		tg3_enable_nvram_access(tp);
 
-			tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
-		}
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+			tg3_get_5752_nvram_info(tp);
+		else
+			tg3_get_nvram_info(tp);
 
-		tg3_get_nvram_info(tp);
 		tg3_get_nvram_size(tp);
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-			u32 nvaccess = tr32(NVRAM_ACCESS);
-
-			tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
-		}
+		tg3_disable_nvram_access(tp);
 
 	} else {
 		tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
@@ -7195,11 +7519,7 @@
 
 	tg3_nvram_lock(tp);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-		u32 nvaccess = tr32(NVRAM_ACCESS);
-
-		tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
-	}
+	tg3_enable_nvram_access(tp);
 
 	tw32(NVRAM_ADDR, offset);
 	ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO |
@@ -7210,11 +7530,7 @@
 
 	tg3_nvram_unlock(tp);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-		u32 nvaccess = tr32(NVRAM_ACCESS);
-
-		tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
-	}
+	tg3_disable_nvram_access(tp);
 
 	return ret;
 }
@@ -7277,7 +7593,7 @@
 
 	while (len) {
 		int j;
-		u32 phy_addr, page_off, size, nvaccess;
+		u32 phy_addr, page_off, size;
 
 		phy_addr = offset & ~pagemask;
 	
@@ -7300,8 +7616,7 @@
 
 		offset = offset + (pagesize - page_off);
 
-		nvaccess = tr32(NVRAM_ACCESS);
-		tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+		tg3_enable_nvram_access(tp);
 
 		/*
 		 * Before we can erase the flash page, we need
@@ -7425,8 +7740,8 @@
 	}
 
 	if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
-		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-		       GRC_LCLCTRL_GPIO_OE1);
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
+		       ~GRC_LCLCTRL_GPIO_OUTPUT1);
 		udelay(40);
 	}
 
@@ -7438,13 +7753,10 @@
 
 		tg3_nvram_lock(tp);
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-			u32 nvaccess = tr32(NVRAM_ACCESS);
-
-			tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
-
+		tg3_enable_nvram_access(tp);
+		if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
+		    !(tp->tg3_flags2 & TG3_FLG2_PROTECTED_NVRAM))
 			tw32(NVRAM_WRITE1, 0x406);
-		}
 
 		grc_mode = tr32(GRC_MODE);
 		tw32(GRC_MODE, grc_mode | GRC_MODE_NVRAM_WR_ENABLE);
@@ -7463,17 +7775,12 @@
 		grc_mode = tr32(GRC_MODE);
 		tw32(GRC_MODE, grc_mode & ~GRC_MODE_NVRAM_WR_ENABLE);
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
-			u32 nvaccess = tr32(NVRAM_ACCESS);
-
-			tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
-		}
+		tg3_disable_nvram_access(tp);
 		tg3_nvram_unlock(tp);
 	}
 
 	if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
-		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-		       GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1);
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 		udelay(40);
 	}
 
@@ -7537,21 +7844,27 @@
 	return NULL;
 }
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+/* Since this function may be called in D3-hot power state during
+ * tg3_init_one(), only config cycles are allowed.
+ */
+static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 {
-	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
-	u32 hw_phy_id, hw_phy_id_masked;
 	u32 val;
-	int eeprom_signature_found, eeprom_phy_serdes, err;
+
+	/* Make sure register accesses (indirect or otherwise)
+	 * will function correctly.
+	 */
+	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+			       tp->misc_host_ctrl);
 
 	tp->phy_id = PHY_ID_INVALID;
-	eeprom_phy_id = PHY_ID_INVALID;
-	eeprom_phy_serdes = 0;
-	eeprom_signature_found = 0;
+	tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
 		u32 nic_cfg, led_cfg;
-		u32 nic_phy_id, ver, cfg2 = 0;
+		u32 nic_phy_id, ver, cfg2 = 0, eeprom_phy_id;
+		int eeprom_phy_serdes = 0;
 
 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
 		tp->nic_sram_data_cfg = nic_cfg;
@@ -7564,8 +7877,6 @@
 		    (ver > 0) && (ver < 0x100))
 			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
 
-		eeprom_signature_found = 1;
-
 		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
 		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
 			eeprom_phy_serdes = 1;
@@ -7581,10 +7892,14 @@
 		} else
 			eeprom_phy_id = 0;
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		tp->phy_id = eeprom_phy_id;
+		if (eeprom_phy_serdes)
+			tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+
+		if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
 			led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
 				    SHASTA_EXT_LED_MODE_MASK);
-		} else
+		else
 			led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK;
 
 		switch (led_cfg) {
@@ -7634,7 +7949,7 @@
 
 		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
 			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+			if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
 				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
 		}
 		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
@@ -7648,6 +7963,13 @@
 		if (cfg2 & (1 << 18))
 			tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
 	}
+}
+
+static int __devinit tg3_phy_probe(struct tg3 *tp)
+{
+	u32 hw_phy_id_1, hw_phy_id_2;
+	u32 hw_phy_id, hw_phy_id_masked;
+	int err;
 
 	/* Reading the PHY ID register can conflict with ASF
 	 * firwmare access to the PHY hardware.
@@ -7676,10 +7998,10 @@
 		if (hw_phy_id_masked == PHY_ID_BCM8002)
 			tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 	} else {
-		if (eeprom_signature_found) {
-			tp->phy_id = eeprom_phy_id;
-			if (eeprom_phy_serdes)
-				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+		if (tp->phy_id != PHY_ID_INVALID) {
+			/* Do nothing, phy ID already set up in
+			 * tg3_get_eeprom_hw_cfg().
+			 */
 		} else {
 			struct subsys_tbl_ent *p;
 
@@ -7750,9 +8072,6 @@
 		err = tg3_init_5401phy_dsp(tp);
 	}
 
-	if (!eeprom_signature_found)
-		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
-
 	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->link_config.advertising =
 			(ADVERTISED_1000baseT_Half |
@@ -7917,6 +8236,12 @@
 	tp->pci_chip_rev_id = (misc_ctrl_reg >>
 			       MISC_HOST_CTRL_CHIPREV_SHIFT);
 
+	/* Wrong chip ID in 5752 A0. This code can be removed later
+	 * as A0 is not in production.
+	 */
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
+		tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+
 	/* Initialize misc host control in PCI block. */
 	tp->misc_host_ctrl |= (misc_ctrl_reg &
 			       MISC_HOST_CTRL_CHIPREV);
@@ -7931,11 +8256,15 @@
 	tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
 	tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+		tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
+
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750))
+	    (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
 		tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+	if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
 		tp->tg3_flags2 |= TG3_FLG2_HW_TSO;
 
 	if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
@@ -8013,6 +8342,31 @@
 		pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
 	}
 
+	/* Get eeprom hw config before calling tg3_set_power_state().
+	 * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
+	 * determined before calling tg3_set_power_state() so that
+	 * we know whether or not to switch out of Vaux power.
+	 * When the flag is set, it means that GPIO1 is used for eeprom
+	 * write protect and also implies that it is a LOM where GPIOs
+	 * are not used to switch power.
+	 */ 
+	tg3_get_eeprom_hw_cfg(tp);
+
+	/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
+	 * GPIO1 driven high will bring 5700's external PHY out of reset.
+	 * It is also used as eeprom write protect on LOMs.
+	 */
+	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
+	    (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT))
+		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+				       GRC_LCLCTRL_GPIO_OUTPUT1);
+	/* Unused GPIO3 must be driven as output on 5752 because there
+	 * are no pull-up resistors on unused GPIO pins.
+	 */
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
+		tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
+
 	/* Force the chip into D0. */
 	err = tg3_set_power_state(tp, 0);
 	if (err) {
@@ -8065,8 +8419,7 @@
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
 		tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
 		tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
 
 	/* Only 5701 and later support tagged irq status mode.
@@ -8628,6 +8981,7 @@
 	case PHY_ID_BCM5704:	return "5704";
 	case PHY_ID_BCM5705:	return "5705";
 	case PHY_ID_BCM5750:	return "5750";
+	case PHY_ID_BCM5752:	return "5752";
 	case PHY_ID_BCM8002:	return "8002/serdes";
 	case 0:			return "serdes";
 	default:		return "unknown";
@@ -8878,7 +9232,7 @@
 	    (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
 		pci_save_state(tp->pdev);
 		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
-		tg3_halt(tp);
+		tg3_halt(tp, 1);
 	}
 
 	err = tg3_test_dma(tp);
@@ -9001,7 +9355,7 @@
 
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
-	tg3_halt(tp);
+	tg3_halt(tp, 1);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d48887d..8de6f21 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -125,6 +125,9 @@
 #define  CHIPREV_ID_5750_A0		 0x4000
 #define  CHIPREV_ID_5750_A1		 0x4001
 #define  CHIPREV_ID_5750_A3		 0x4003
+#define  CHIPREV_ID_5752_A0_HW		 0x5000
+#define  CHIPREV_ID_5752_A0		 0x6000
+#define  CHIPREV_ID_5752_A1		 0x6001
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -132,6 +135,7 @@
 #define   ASIC_REV_5704			 0x02
 #define   ASIC_REV_5705			 0x03
 #define   ASIC_REV_5750			 0x04
+#define   ASIC_REV_5752			 0x06
 #define  GET_CHIP_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX		 0x70
 #define   CHIPREV_5700_BX		 0x71
@@ -1307,6 +1311,9 @@
 #define  GRC_LCLCTRL_CLEARINT		0x00000002
 #define  GRC_LCLCTRL_SETINT		0x00000004
 #define  GRC_LCLCTRL_INT_ON_ATTN	0x00000008
+#define  GRC_LCLCTRL_GPIO_INPUT3	0x00000020
+#define  GRC_LCLCTRL_GPIO_OE3		0x00000040
+#define  GRC_LCLCTRL_GPIO_OUTPUT3	0x00000080
 #define  GRC_LCLCTRL_GPIO_INPUT0	0x00000100
 #define  GRC_LCLCTRL_GPIO_INPUT1	0x00000200
 #define  GRC_LCLCTRL_GPIO_INPUT2	0x00000400
@@ -1392,6 +1399,20 @@
 #define  FLASH_VENDOR_SAIFUN		 0x01000003
 #define  FLASH_VENDOR_SST_SMALL		 0x00000001
 #define  FLASH_VENDOR_SST_LARGE		 0x02000001
+#define  NVRAM_CFG1_5752VENDOR_MASK	 0x03c00003
+#define  FLASH_5752VENDOR_ATMEL_EEPROM_64KHZ	 0x00000000
+#define  FLASH_5752VENDOR_ATMEL_EEPROM_376KHZ	 0x02000000
+#define  FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED	 0x02000003
+#define  FLASH_5752VENDOR_ST_M45PE10	 0x02400000
+#define  FLASH_5752VENDOR_ST_M45PE20	 0x02400002
+#define  FLASH_5752VENDOR_ST_M45PE40	 0x02400001
+#define  NVRAM_CFG1_5752PAGE_SIZE_MASK	 0x70000000
+#define  FLASH_5752PAGE_SIZE_256	 0x00000000
+#define  FLASH_5752PAGE_SIZE_512	 0x10000000
+#define  FLASH_5752PAGE_SIZE_1K		 0x20000000
+#define  FLASH_5752PAGE_SIZE_2K		 0x30000000
+#define  FLASH_5752PAGE_SIZE_4K		 0x40000000
+#define  FLASH_5752PAGE_SIZE_264	 0x50000000
 #define NVRAM_CFG2			0x00007018
 #define NVRAM_CFG3			0x0000701c
 #define NVRAM_SWARB			0x00007020
@@ -2100,6 +2121,9 @@
 #define TG3_FLG2_HW_TSO			0x00010000
 #define TG3_FLG2_SERDES_PREEMPHASIS	0x00020000
 #define TG3_FLG2_5705_PLUS		0x00040000
+#define TG3_FLG2_5750_PLUS		0x00080000
+#define TG3_FLG2_PROTECTED_NVRAM	0x00100000
+#define TG3_FLG2_USING_MSI		0x00200000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -2145,6 +2169,7 @@
 #define PHY_ID_BCM5704			0x60008190
 #define PHY_ID_BCM5705			0x600081a0
 #define PHY_ID_BCM5750			0x60008180
+#define PHY_ID_BCM5752			0x60008100
 #define PHY_ID_BCM8002			0x60010140
 #define PHY_ID_INVALID			0xffffffff
 #define PHY_ID_REV_MASK			0x0000000f
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 3579193..66b9466 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -26,7 +26,7 @@
 # There is no way to detect a comtrol sv11 - force it modular for now.
 config HOSTESS_SV11
 	tristate "Comtrol Hostess SV-11 support"
-	depends on WAN && ISA && m
+	depends on WAN && ISA && m && ISA_DMA_API
 	help
 	  Driver for Comtrol Hostess SV-11 network card which
 	  operates on low speed synchronous serial links at up to
@@ -38,7 +38,7 @@
 # The COSA/SRP driver has not been tested as non-modular yet.
 config COSA
 	tristate "COSA/SRP sync serial boards support"
-	depends on WAN && ISA && m
+	depends on WAN && ISA && m && ISA_DMA_API
 	---help---
 	  Driver for COSA and SRP synchronous serial boards.
 
@@ -127,7 +127,7 @@
 # There is no way to detect a Sealevel board. Force it modular
 config SEALEVEL_4021
 	tristate "Sealevel Systems 4021 support"
-	depends on WAN && ISA && m
+	depends on WAN && ISA && m && ISA_DMA_API
 	help
 	  This is a driver for the Sealevel Systems ACB 56 serial I/O adapter.
 
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index 5b48cd8..02d57c0 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -436,9 +436,7 @@
 	}
 
 	if (err) {
-		if (chan->local_addr)
-			kfree(chan->local_addr);
-
+		kfree(chan->local_addr);
 		kfree(chan);
 		return err;
 	}
@@ -458,9 +456,7 @@
 		struct cycx_x25_channel *chan = dev->priv;
 
 		if (chan->svc) {
-			if (chan->local_addr)
-				kfree(chan->local_addr);
-
+			kfree(chan->local_addr);
 			if (chan->state == WAN_CONNECTED)
 				del_timer(&chan->timer);
 		}
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index d67be25..3e7753b 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -3427,7 +3427,7 @@
 {
 	static int first_time = 1;
 	ucchar cpc_rev_id;
-	int err = 0, eeprom_outdated = 0;
+	int err, eeprom_outdated = 0;
 	ucshort device_id;
 	pc300_t *card;
 
@@ -3439,15 +3439,21 @@
 #endif
 	}
 
+	if ((err = pci_enable_device(pdev)) < 0)
+		return err;
+
 	card = (pc300_t *) kmalloc(sizeof(pc300_t), GFP_KERNEL);
 	if (card == NULL) {
 		printk("PC300 found at RAM 0x%08lx, "
 		       "but could not allocate card structure.\n",
 		       pci_resource_start(pdev, 3));
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_disable_dev;
 	}
 	memset(card, 0, sizeof(pc300_t));
 
+	err = -ENODEV;
+
 	/* read PCI configuration area */
 	device_id = ent->device;
 	card->hw.irq = pdev->irq;
@@ -3507,7 +3513,6 @@
 		printk("PC300 found at RAM 0x%08x, "
 		       "but could not allocate PLX mem region.\n",
 		       card->hw.ramphys);
-		err = -ENODEV;
 		goto err_release_io;
 	}
 	if (!request_mem_region(card->hw.ramphys, card->hw.alloc_ramsize,
@@ -3515,7 +3520,6 @@
 		printk("PC300 found at RAM 0x%08x, "
 		       "but could not allocate RAM mem region.\n",
 		       card->hw.ramphys);
-		err = -ENODEV;
 		goto err_release_plx;
 	}
 	if (!request_mem_region(card->hw.scaphys, card->hw.scasize,
@@ -3523,13 +3527,9 @@
 		printk("PC300 found at RAM 0x%08x, "
 		       "but could not allocate SCA mem region.\n",
 		       card->hw.ramphys);
-		err = -ENODEV;
 		goto err_release_ram;
 	}
 
-	if ((err = pci_enable_device(pdev)) != 0)
-		goto err_release_sca;
-
 	card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize);
 	card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize);
 	card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize);
@@ -3619,7 +3619,6 @@
 		iounmap(card->hw.falcbase);
 		release_mem_region(card->hw.falcphys, card->hw.falcsize);
 	}
-err_release_sca:
 	release_mem_region(card->hw.scaphys, card->hw.scasize);
 err_release_ram:
 	release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
@@ -3628,7 +3627,9 @@
 err_release_io:
 	release_region(card->hw.iophys, card->hw.iosize);
 	kfree(card);
-	return -ENODEV;
+err_disable_dev:
+	pci_disable_device(pdev);
+	return err;
 }
 
 static void __devexit cpc_remove_one(struct pci_dev *pdev)
@@ -3662,6 +3663,7 @@
 		if (card->hw.irq)
 			free_irq(card->hw.irq, card);
 		kfree(card);
+		pci_disable_device(pdev);
 	}
 }
 
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 29f84ad..8454bf6 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -400,10 +400,8 @@
 		cpc_tty->buf_rx.last = NULL;
 	}
 	
-	if (cpc_tty->buf_tx) {
-		kfree(cpc_tty->buf_tx);
-		cpc_tty->buf_tx = NULL;
-	}
+	kfree(cpc_tty->buf_tx);
+	cpc_tty->buf_tx = NULL;
 
 	CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name);
 	
@@ -666,7 +664,7 @@
 	unsigned long port;
 	int i, j;
 	st_cpc_tty_area *cpc_tty; 
-	volatile st_cpc_rx_buf * buf;
+	volatile st_cpc_rx_buf *buf;
 	char flags=0,flg_rx=1; 
 	struct tty_ldisc *ld;
 
@@ -680,9 +678,9 @@
 			cpc_tty = &cpc_tty_area[port];
 		
 			if ((buf=cpc_tty->buf_rx.first) != 0) {
-				if(cpc_tty->tty) {
+				if (cpc_tty->tty) {
 					ld = tty_ldisc_ref(cpc_tty->tty);
-					if(ld) {
+					if (ld) {
 						if (ld->receive_buf) {
 							CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
 							ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
@@ -691,7 +689,7 @@
 					}
 				}	
 				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
-				kfree((unsigned char *)buf);
+				kfree(buf);
 				buf = cpc_tty->buf_rx.first;
 				flg_rx = 1;
 			}
@@ -733,7 +731,7 @@
 
 void cpc_tty_receive(pc300dev_t *pc300dev)
 {
-	st_cpc_tty_area    *cpc_tty; 
+	st_cpc_tty_area *cpc_tty; 
 	pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
 	pc300_t *card = (pc300_t *)pc300chan->card; 
 	int ch = pc300chan->channel; 
@@ -742,7 +740,7 @@
 	int rx_len, rx_aux; 
 	volatile unsigned char status; 
 	unsigned short first_bd = pc300chan->rx_first_bd;
-	st_cpc_rx_buf	*new=NULL;
+	st_cpc_rx_buf *new = NULL;
 	unsigned char dsr_rx;
 
 	if (pc300dev->cpc_tty == NULL) { 
@@ -762,7 +760,7 @@
 			if (status & DST_EOM) {
 				break;
 			}
-			ptdescr=(pcsca_bd_t __iomem *)(card->hw.rambase+cpc_readl(&ptdescr->next));
+			ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase+cpc_readl(&ptdescr->next));
 		}
 			
 		if (!rx_len) { 
@@ -771,10 +769,7 @@
 				cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
 						RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
 			}
-			if (new) {
-				kfree(new);
-				new = NULL;
-			}
+			kfree(new);
 			return; 
 		}
 		
@@ -787,7 +782,7 @@
 			continue;
 		} 
 		
-		new = (st_cpc_rx_buf *) kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
+		new = (st_cpc_rx_buf *)kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
 		if (new == 0) {
 			cpc_tty_rx_disc_frame(pc300chan);
 			continue;
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index afbe002..496d292 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -3664,15 +3664,10 @@
 		chdlc_disable_comm_shutdown(card);
 		unlock_adapter_irq(&card->wandev.lock,&smp_flags);
 
-		if (card->tty_buf){
-			kfree(card->tty_buf);
-			card->tty_buf=NULL;			
-		}
-
-		if (card->tty_rx){
-			kfree(card->tty_rx);
-			card->tty_rx=NULL;
-		}
+		kfree(card->tty_buf);
+		card->tty_buf = NULL;			
+		kfree(card->tty_rx);
+		card->tty_rx = NULL;
 	}
 	return;
 }
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 8c5cfcb..1c540d8 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -107,13 +107,9 @@
 static void x25_asy_free(struct x25_asy *sl)
 {
 	/* Free all X.25 frame buffers. */
-	if (sl->rbuff)  {
-		kfree(sl->rbuff);
-	}
+	kfree(sl->rbuff);
 	sl->rbuff = NULL;
-	if (sl->xbuff)  {
-		kfree(sl->xbuff);
-	}
+	kfree(sl->xbuff);
 	sl->xbuff = NULL;
 
 	if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) {
@@ -134,10 +130,8 @@
 	{
 		printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n",
 		       dev->name);
-		if (xbuff != NULL)  
-			kfree(xbuff);
-		if (rbuff != NULL)  
-			kfree(rbuff);
+		kfree(xbuff);
+		kfree(rbuff);
 		return -ENOMEM;
 	}
 
@@ -169,10 +163,8 @@
 
 	spin_unlock_bh(&sl->lock);
 
-	if (xbuff != NULL) 
-		kfree(xbuff);
-	if (rbuff != NULL)
-		kfree(rbuff);
+	kfree(xbuff);
+	kfree(rbuff);
 	return 0;
 }
 
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index 9abedea..a72006c 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -18,13 +18,13 @@
 unsigned long fs_cpu_buffer_size = 8192;
 unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
 
-static ssize_t depth_read(struct file * file, char * buf, size_t count, loff_t * offset)
+static ssize_t depth_read(struct file * file, char __user * buf, size_t count, loff_t * offset)
 {
 	return oprofilefs_ulong_to_user(backtrace_depth, buf, count, offset);
 }
 
 
-static ssize_t depth_write(struct file * file, char const * buf, size_t count, loff_t * offset)
+static ssize_t depth_write(struct file * file, char const __user * buf, size_t count, loff_t * offset)
 {
 	unsigned long val;
 	int retval;
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 731010e..16a2e6a 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -34,7 +34,7 @@
 
 config PARPORT_PC
 	tristate "PC-style hardware"
-	depends on PARPORT && (!SPARC64 || PCI) && (!SPARC32 || BROKEN)
+	depends on PARPORT && (!SPARC64 || PCI) && !SPARC32
 	---help---
 	  You should say Y here if you have a PC-style parallel port. All
 	  IBM PC compatible computers and some Alphas have PC-style
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index c5774e7..e7f3bcb 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -67,6 +67,10 @@
 
 #define PARPORT_PC_MAX_PORTS PARPORT_MAX
 
+#ifdef CONFIG_ISA_DMA_API
+#define HAS_DMA
+#endif
+
 /* ECR modes */
 #define ECR_SPP 00
 #define ECR_PS2 01
@@ -610,6 +614,7 @@
 	return length - left;
 }
 
+#ifdef HAS_DMA
 static size_t parport_pc_fifo_write_block_dma (struct parport *port,
 					       const void *buf, size_t length)
 {
@@ -732,6 +737,17 @@
 dump_parport_state ("leave fifo_write_block_dma", port);
 	return length - left;
 }
+#endif
+
+static inline size_t parport_pc_fifo_write_block(struct parport *port,
+					       const void *buf, size_t length)
+{
+#ifdef HAS_DMA
+	if (port->dma != PARPORT_DMA_NONE)
+		return parport_pc_fifo_write_block_dma (port, buf, length);
+#endif
+	return parport_pc_fifo_write_block_pio (port, buf, length);
+}
 
 /* Parallel Port FIFO mode (ECP chipsets) */
 static size_t parport_pc_compat_write_block_pio (struct parport *port,
@@ -758,10 +774,7 @@
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
 
 	/* Write the data to the FIFO. */
-	if (port->dma != PARPORT_DMA_NONE)
-		written = parport_pc_fifo_write_block_dma (port, buf, length);
-	else
-		written = parport_pc_fifo_write_block_pio (port, buf, length);
+	written = parport_pc_fifo_write_block(port, buf, length);
 
 	/* Finish up. */
 	/* For some hardware we don't want to touch the mode until
@@ -856,10 +869,7 @@
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
 
 	/* Write the data to the FIFO. */
-	if (port->dma != PARPORT_DMA_NONE)
-		written = parport_pc_fifo_write_block_dma (port, buf, length);
-	else
-		written = parport_pc_fifo_write_block_pio (port, buf, length);
+	written = parport_pc_fifo_write_block(port, buf, length);
 
 	/* Finish up. */
 	/* For some hardware we don't want to touch the mode until
@@ -2285,6 +2295,7 @@
 		}
 
 #ifdef CONFIG_PARPORT_PC_FIFO
+#ifdef HAS_DMA
 		if (p->dma != PARPORT_DMA_NONE) {
 			if (request_dma (p->dma, p->name)) {
 				printk (KERN_WARNING "%s: dma %d in use, "
@@ -2306,7 +2317,8 @@
 				}
 			}
 		}
-#endif /* CONFIG_PARPORT_PC_FIFO */
+#endif
+#endif
 	}
 
 	/* Done probing.  Now put the port into a sensible start-up state. */
@@ -2367,11 +2379,13 @@
 	if (p->modes & PARPORT_MODE_ECP)
 		release_region(p->base_hi, 3);
 #ifdef CONFIG_PARPORT_PC_FIFO
+#ifdef HAS_DMA
 	if (priv->dma_buf)
 		pci_free_consistent(priv->dev, PAGE_SIZE,
 				    priv->dma_buf,
 				    priv->dma_handle);
-#endif /* CONFIG_PARPORT_PC_FIFO */
+#endif
+#endif
 	kfree (p->private_data);
 	parport_put_port(p);
 	kfree (ops); /* hope no-one cached it */
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index d471b3e..021d0f7 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -120,6 +120,10 @@
 
 /**
  * pci_visit_dev - scans the pci buses.
+ * @fn: callback functions that are called while visiting
+ * @wrapped_dev: the device to scan
+ * @wrapped_parent: the bus where @wrapped_dev is connected to
+ *
  * Every bus and every function is presented to a custom
  * function that can act upon it.
  */
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
index 5bc039d..c22e028 100644
--- a/drivers/pci/hotplug/ibmphp.h
+++ b/drivers/pci/hotplug/ibmphp.h
@@ -196,7 +196,7 @@
 
 
 /********************************************************************
-*   THREE TYPE OF HOT PLUG CONTROLER                                *
+*   THREE TYPE OF HOT PLUG CONTROLLER                                *
 ********************************************************************/
 
 struct isa_ctlr_access {
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index 6894b54..1a3eb8d 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -64,7 +64,7 @@
 #define WPG_I2C_OR		0x2000	// I2C OR operation
 
 //----------------------------------------------------------------------------
-// Command set for I2C Master Operation Setup Regisetr
+// Command set for I2C Master Operation Setup Register
 //----------------------------------------------------------------------------
 #define WPG_READATADDR_MASK	0x00010000	// read,bytes,I2C shifted,index
 #define WPG_WRITEATADDR_MASK	0x40010000	// write,bytes,I2C shifted,index
@@ -835,7 +835,7 @@
 		if (ibmphp_shutdown) 
 			break;
 		
-		/* try to get the lock to do some kind of harware access */
+		/* try to get the lock to do some kind of hardware access */
 		down (&semOperations);
 
 		switch (poll_state) {
@@ -906,7 +906,7 @@
 				poll_state = POLL_LATCH_REGISTER;
 			break;
 		}	
-		/* give up the harware semaphore */
+		/* give up the hardware semaphore */
 		up (&semOperations);
 		/* sleep for a short time just for good measure */
 		msleep(100);
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index 2335fac..8122fe7 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -1308,10 +1308,10 @@
 			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
 		} else {
 			/* This is Memory */
-			start_address &= PCI_BASE_ADDRESS_MEM_MASK;
 			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
 				/* pfmem */
 				debug ("start address of pfmem is %x\n", start_address);
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
 
 				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {
 					err ("cannot find corresponding PFMEM resource to remove\n");
@@ -1325,6 +1325,8 @@
 			} else {
 				/* regular memory */
 				debug ("start address of mem is %x\n", start_address);
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
+
 				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {
 					err ("cannot find corresponding MEM resource to remove\n");
 					return -EIO;
@@ -1422,9 +1424,9 @@
 			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */
 		} else {
 			/* This is Memory */
-			start_address &= PCI_BASE_ADDRESS_MEM_MASK;
 			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {
 				/* pfmem */
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
 				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {
 					err ("cannot find corresponding PFMEM resource to remove\n");
 					return -EINVAL;
@@ -1436,6 +1438,7 @@
 				}
 			} else {
 				/* regular memory */
+				start_address &= PCI_BASE_ADDRESS_MEM_MASK;
 				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {
 					err ("cannot find corresponding MEM resource to remove\n");
 					return -EINVAL;
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h
index 57ace32..88d44f7 100644
--- a/drivers/pci/hotplug/pci_hotplug.h
+++ b/drivers/pci/hotplug/pci_hotplug.h
@@ -150,7 +150,7 @@
  * @name: the name of the slot being registered.  This string must
  * be unique amoung slots registered on this system.
  * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
- * @info: pointer to the &struct hotplug_slot_info for the inital values for
+ * @info: pointer to the &struct hotplug_slot_info for the initial values for
  * this slot.
  * @release: called during pci_hp_deregister to free memory allocated in a
  * hotplug_slot structure.
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 72baf74..ed1fd8d 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -90,6 +90,22 @@
   	.get_cur_bus_speed =	get_cur_bus_speed,
 };
 
+/**
+ * release_slot - free up the memory used by a slot
+ * @hotplug_slot: slot to free
+ */
+static void release_slot(struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = hotplug_slot->private;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	kfree(slot->hotplug_slot->info);
+	kfree(slot->hotplug_slot->name);
+	kfree(slot->hotplug_slot);
+	kfree(slot);
+}
+
 static int init_slots(struct controller *ctrl)
 {
 	struct slot *new_slot;
@@ -139,7 +155,8 @@
 
 		/* register this slot with the hotplug pci core */
 		new_slot->hotplug_slot->private = new_slot;
-		make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
+		new_slot->hotplug_slot->release = &release_slot;
+		make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
 		new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops;
 
 		new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
@@ -188,10 +205,6 @@
 	while (old_slot) {
 		next_slot = old_slot->next;
 		pci_hp_deregister (old_slot->hotplug_slot);
-		kfree(old_slot->hotplug_slot->info);
-		kfree(old_slot->hotplug_slot->name);
-		kfree(old_slot->hotplug_slot);
-		kfree(old_slot);
 		old_slot = next_slot;
 	}
 
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
index 6605d6b..3194d51c 100644
--- a/drivers/pci/hotplug/pcihp_skeleton.c
+++ b/drivers/pci/hotplug/pcihp_skeleton.c
@@ -297,7 +297,7 @@
 		hotplug_slot->ops = &skel_hotplug_slot_ops;
 		
 		/*
-		 * Initilize the slot info structure with some known
+		 * Initialize the slot info structure with some known
 		 * good values.
 		 */
 		info->power_status = get_power_status(slot);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 22ecd3b..30206ac 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -522,7 +522,7 @@
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
  *
- * Setup the MSI capability structure of device funtion with a single
+ * Setup the MSI capability structure of device function with a single
  * MSI vector, regardless of device function is capable of handling
  * multiple messages. A return of zero indicates the successful setup
  * of an entry zero with the new MSI vector or non-zero for otherwise.
@@ -599,7 +599,7 @@
  * msix_capability_init - configure device's MSI-X capability
  * @dev: pointer to the pci_dev data structure of MSI-X device function
  *
- * Setup the MSI-X capability structure of device funtion with a
+ * Setup the MSI-X capability structure of device function with a
  * single MSI-X vector. A return of zero indicates the successful setup of
  * requested MSI-X entries with allocated vectors or non-zero for otherwise.
  **/
@@ -1074,7 +1074,7 @@
  * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
  * @dev: pointer to the pci_dev data structure of MSI(X) device function
  *
- * Being called during hotplug remove, from which the device funciton
+ * Being called during hotplug remove, from which the device function
  * is hot-removed. All previous assigned MSI/MSI-X vectors, if
  * allocated for this device function, are reclaimed to unused state,
  * which may be used later on.
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 968eb32..bc01d34 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -19,7 +19,7 @@
 
 static u32 ctrlset_buf[3] = {0, 0, 0};
 static u32 global_ctrlsets = 0;
-u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
+static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
 
 static acpi_status  
 acpi_query_osc (
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 37b7961..fe98553 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -318,6 +318,14 @@
 	return 0;
 }
 
+static void pci_device_shutdown(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+
+	if (drv && drv->shutdown)
+		drv->shutdown(pci_dev);
+}
 
 #define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj)
 #define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
@@ -373,7 +381,7 @@
  * 
  * Adds the driver structure to the list of registered drivers.
  * Returns a negative value on error, otherwise 0. 
- * If no error occured, the driver remains registered even if 
+ * If no error occurred, the driver remains registered even if 
  * no device was claimed during registration.
  */
 int pci_register_driver(struct pci_driver *drv)
@@ -385,6 +393,7 @@
 	drv->driver.bus = &pci_bus_type;
 	drv->driver.probe = pci_device_probe;
 	drv->driver.remove = pci_device_remove;
+	drv->driver.shutdown = pci_device_shutdown,
 	drv->driver.owner = drv->owner;
 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
 	pci_init_dynids(&drv->dynids);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index d57ae71..8568b20 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -91,6 +91,7 @@
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = 64;
 	loff_t init_off = off;
+	u8 *data = (u8*) buf;
 
 	/* Several chips lock up trying to read undefined config space */
 	if (capable(CAP_SYS_ADMIN)) {
@@ -108,30 +109,47 @@
 		size = count;
 	}
 
-	while (off & 3) {
-		unsigned char val;
+	if ((off & 1) && size) {
+		u8 val;
 		pci_read_config_byte(dev, off, &val);
-		buf[off - init_off] = val;
+		data[off - init_off] = val;
 		off++;
-		if (--size == 0)
-			break;
+		size--;
+	}
+
+	if ((off & 3) && size > 2) {
+		u16 val;
+		pci_read_config_word(dev, off, &val);
+		data[off - init_off] = val & 0xff;
+		data[off - init_off + 1] = (val >> 8) & 0xff;
+		off += 2;
+		size -= 2;
 	}
 
 	while (size > 3) {
-		unsigned int val;
+		u32 val;
 		pci_read_config_dword(dev, off, &val);
-		buf[off - init_off] = val & 0xff;
-		buf[off - init_off + 1] = (val >> 8) & 0xff;
-		buf[off - init_off + 2] = (val >> 16) & 0xff;
-		buf[off - init_off + 3] = (val >> 24) & 0xff;
+		data[off - init_off] = val & 0xff;
+		data[off - init_off + 1] = (val >> 8) & 0xff;
+		data[off - init_off + 2] = (val >> 16) & 0xff;
+		data[off - init_off + 3] = (val >> 24) & 0xff;
 		off += 4;
 		size -= 4;
 	}
 
-	while (size > 0) {
-		unsigned char val;
+	if (size >= 2) {
+		u16 val;
+		pci_read_config_word(dev, off, &val);
+		data[off - init_off] = val & 0xff;
+		data[off - init_off + 1] = (val >> 8) & 0xff;
+		off += 2;
+		size -= 2;
+	}
+
+	if (size > 0) {
+		u8 val;
 		pci_read_config_byte(dev, off, &val);
-		buf[off - init_off] = val;
+		data[off - init_off] = val;
 		off++;
 		--size;
 	}
@@ -145,6 +163,7 @@
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = count;
 	loff_t init_off = off;
+	u8 *data = (u8*) buf;
 
 	if (off > dev->cfg_size)
 		return 0;
@@ -152,26 +171,41 @@
 		size = dev->cfg_size - off;
 		count = size;
 	}
-
-	while (off & 3) {
-		pci_write_config_byte(dev, off, buf[off - init_off]);
+	
+	if ((off & 1) && size) {
+		pci_write_config_byte(dev, off, data[off - init_off]);
 		off++;
-		if (--size == 0)
-			break;
+		size--;
 	}
+	
+	if ((off & 3) && size > 2) {
+		u16 val = data[off - init_off];
+		val |= (u16) data[off - init_off + 1] << 8;
+                pci_write_config_word(dev, off, val);
+                off += 2;
+                size -= 2;
+        }
 
 	while (size > 3) {
-		unsigned int val = buf[off - init_off];
-		val |= (unsigned int) buf[off - init_off + 1] << 8;
-		val |= (unsigned int) buf[off - init_off + 2] << 16;
-		val |= (unsigned int) buf[off - init_off + 3] << 24;
+		u32 val = data[off - init_off];
+		val |= (u32) data[off - init_off + 1] << 8;
+		val |= (u32) data[off - init_off + 2] << 16;
+		val |= (u32) data[off - init_off + 3] << 24;
 		pci_write_config_dword(dev, off, val);
 		off += 4;
 		size -= 4;
 	}
+	
+	if (size >= 2) {
+		u16 val = data[off - init_off];
+		val |= (u16) data[off - init_off + 1] << 8;
+		pci_write_config_word(dev, off, val);
+		off += 2;
+		size -= 2;
+	}
 
-	while (size > 0) {
-		pci_write_config_byte(dev, off, buf[off - init_off]);
+	if (size) {
+		pci_write_config_byte(dev, off, data[off - init_off]);
 		off++;
 		--size;
 	}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bfbff83..f04b9ff 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
+#include "pci.h"
 
 
 /**
@@ -398,10 +399,10 @@
 {
 	int err;
 
-	dev->is_enabled = 1;
 	if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1)))
 		return err;
 	pci_fixup_device(pci_fixup_enable, dev);
+	dev->is_enabled = 1;
 	return 0;
 }
 
@@ -427,16 +428,15 @@
 {
 	u16 pci_command;
 	
-	dev->is_enabled = 0;
-	dev->is_busmaster = 0;
-
 	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
 	if (pci_command & PCI_COMMAND_MASTER) {
 		pci_command &= ~PCI_COMMAND_MASTER;
 		pci_write_config_word(dev, PCI_COMMAND, pci_command);
 	}
+	dev->is_busmaster = 0;
 
 	pcibios_disable_device(dev);
+	dev->is_enabled = 0;
 }
 
 /**
@@ -749,17 +749,6 @@
 }
     
 int
-pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	if (!pci_dac_dma_supported(dev, mask))
-		return -EIO;
-
-	dev->dma_mask = mask;
-
-	return 0;
-}
-
-int
 pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 {
 	if (!pci_dma_supported(dev, mask))
@@ -821,7 +810,6 @@
 EXPORT_SYMBOL(pci_set_mwi);
 EXPORT_SYMBOL(pci_clear_mwi);
 EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_dac_set_dma_mask);
 EXPORT_SYMBOL(pci_set_consistent_dma_mask);
 EXPORT_SYMBOL(pci_assign_resource);
 EXPORT_SYMBOL(pci_find_parent_resource);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6f0edad..b7ae878 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
+#include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
 #define CARDBUS_RESERVE_BUSNR	3
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 84cc4f6..e68bbfb 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -15,6 +15,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
+#include "pci.h"
 
 static int proc_initialized;	/* = 0 */
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 15a3980..026aa04 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -18,6 +18,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include "pci.h"
 
 /* Deal with broken BIOS'es that neglect to enable passive release,
    which can cause problems in combination with the 82441FX/PPro MTRRs */
@@ -328,6 +329,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,		quirk_ich4_lpc_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		quirk_ich4_lpc_acpi );
 
 /*
  * VIA ACPI: One IO region pointed to by longword at
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 3e64ff6..838575e 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -14,7 +14,7 @@
 
 /**
  * pci_enable_rom - enable ROM decoding for a PCI device
- * @dev: PCI device to enable
+ * @pdev: PCI device to enable
  *
  * Enable ROM decoding on @dev.  This involves simply turning on the last
  * bit of the PCI ROM BAR.  Note that some cards may share address decoders
@@ -32,7 +32,7 @@
 
 /**
  * pci_disable_rom - disable ROM decoding for a PCI device
- * @dev: PCI device to disable
+ * @pdev: PCI device to disable
  *
  * Disable ROM decoding on a PCI device by turning off the last bit in the
  * ROM BAR.
@@ -47,7 +47,7 @@
 
 /**
  * pci_map_rom - map a PCI ROM to kernel space
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
  * @size: pointer to receive size of pci window over ROM
  * @return: kernel virtual pointer to image of ROM
  *
@@ -132,7 +132,7 @@
 
 /**
  * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
  * @size: pointer to receive size of pci window over ROM
  * @return: kernel virtual pointer to image of ROM
  *
@@ -166,7 +166,7 @@
 
 /**
  * pci_unmap_rom - unmap the ROM from kernel space
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
  * @rom: virtual address of the previous mapping
  *
  * Remove a mapping of a previously mapped ROM
@@ -187,7 +187,7 @@
 
 /**
  * pci_remove_rom - disable the ROM and remove its sysfs attribute
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
  *
  * Remove the rom file in sysfs and disable ROM decoding.
  */
@@ -206,7 +206,7 @@
 /**
  * pci_cleanup_rom - internal routine for freeing the ROM copy created
  * by pci_map_rom_copy called from remove.c
- * @dev: pointer to pci device struct
+ * @pdev: pointer to pci device struct
  *
  * Free the copied ROM if we allocated one.
  */
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 3f43643..20642f0 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -744,7 +744,7 @@
 
 	for (i = 0; i < MAX_SOCKETS; i++) {
 		socket[i].io_base = pci_resource_start(dev, 0);
-		socket[i].socket.features |= SS_CAP_PCCARD;
+		socket[i].socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD;
 		socket[i].socket.map_size = 0x1000;
 		socket[i].socket.irq_mask = mask;
 		socket[i].socket.pci_irq  = dev->irq;
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 52c073a..a8a1d10 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -442,6 +442,25 @@
 }
 
 
+/* changes the irq of func1 to match that of func0 */
+static int ti12xx_align_irqs(struct yenta_socket *socket, int *old_irq)
+{
+	struct pci_dev *func0;
+
+	/* find func0 device */
+	func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07);
+	if (!func0)
+		return 0;
+
+	if (old_irq)
+		*old_irq = socket->cb_irq;
+	socket->cb_irq = socket->dev->irq = func0->irq;
+
+	pci_dev_put(func0);
+
+	return 1;
+}
+
 /*
  * ties INTA and INTB together. also changes the devices irq to that of
  * the function 0 device. call from func1 only.
@@ -449,26 +468,22 @@
  */
 static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq)
 {
-	struct pci_dev *func0;
 	u32 sysctl;
+	int ret;
 
 	sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
 	if (sysctl & TI122X_SCR_INTRTIE)
 		return 0;
 
-	/* find func0 device */
-	func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07);
-	if (!func0)
+	/* align */
+	ret = ti12xx_align_irqs(socket, old_irq);
+	if (!ret)
 		return 0;
 
-	/* change the interrupt to match func0, tie 'em up */
-	*old_irq = socket->cb_irq;
-	socket->cb_irq = socket->dev->irq = func0->irq;
+	/* tie */
 	sysctl |= TI122X_SCR_INTRTIE;
 	config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl);
 
-	pci_dev_put(func0);
-
 	return 1;
 }
 
@@ -489,7 +504,7 @@
  */
 static void ti12xx_irqroute_func1(struct yenta_socket *socket)
 {
-	u32 mfunc, mfunc_old, devctl;
+	u32 mfunc, mfunc_old, devctl, sysctl;
 	int pci_irq_status;
 
 	mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
@@ -497,6 +512,11 @@
 	printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
 	       pci_name(socket->dev), mfunc, devctl);
 
+	/* if IRQs are configured as tied, align irq of func1 with func0 */
+	sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
+	if (sysctl & TI122X_SCR_INTRTIE)
+		ti12xx_align_irqs(socket, NULL);
+
 	/* make sure PCI interrupts are enabled before probing */
 	ti_init(socket);
 
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 639e042..65ecef7 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -253,7 +253,7 @@
 
 /**
  * pnp_clean_resources - clears resources that were not manually set
- * @res - the resources to clean
+ * @res: the resources to clean
  *
  */
 static void pnp_clean_resource_table(struct pnp_resource_table * res)
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index c0ddb1e..dd61e09 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -94,8 +94,8 @@
 pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
 {
 	int i = 0;
-	while (!(res->dma_resource[i].flags & IORESOURCE_UNSET) &&
-			i < PNP_MAX_DMA)
+	while (i < PNP_MAX_DMA &&
+			!(res->dma_resource[i].flags & IORESOURCE_UNSET))
 		i++;
 	if (i < PNP_MAX_DMA) {
 		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index 618ac15..79bce7b 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -72,7 +72,9 @@
 pnpbios_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
 {
 	int i = 0;
-	while (!(res->dma_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_DMA) i++;
+	while (i < PNP_MAX_DMA &&
+			!(res->dma_resource[i].flags & IORESOURCE_UNSET))
+		i++;
 	if (i < PNP_MAX_DMA) {
 		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
 		if (dma == -1) {
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index b755bac..02cfe24 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.158 $
+ * $Revision: 1.161 $
  */
 
 #include <linux/config.h>
@@ -1131,13 +1131,17 @@
 	request_queue_t *queue;
 	struct request *req;
 	struct dasd_ccw_req *cqr;
-	int nr_queued;
+	int nr_queued, feature_ro;
 
 	queue = device->request_queue;
 	/* No queue ? Then there is nothing to do. */
 	if (queue == NULL)
 		return;
 
+	feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
+	if (feature_ro < 0) 	/* no devmap */
+		return;
+
 	/*
 	 * We requeue request from the block device queue to the ccw
 	 * queue only in two states. In state DASD_STATE_READY the
@@ -1157,8 +1161,8 @@
 	       elv_next_request(queue) &&
 		nr_queued < DASD_CHANQ_MAX_SIZE) {
 		req = elv_next_request(queue);
-		if (test_bit(DASD_FLAG_RO, &device->flags) &&
-		    rq_data_dir(req) == WRITE) {
+
+		if (feature_ro && rq_data_dir(req) == WRITE) {
 			DBF_DEV_EVENT(DBF_ERR, device,
 				      "Rejecting write request %p",
 				      req);
@@ -1631,6 +1635,7 @@
 	blk_queue_max_hw_segments(device->request_queue, -1L);
 	blk_queue_max_segment_size(device->request_queue, -1L);
 	blk_queue_segment_boundary(device->request_queue, -1L);
+	blk_queue_ordered(device->request_queue, 1);
 }
 
 /*
@@ -1803,13 +1808,17 @@
 
 {
 	struct dasd_device *device;
-	int rc;
+	int feature_diag, rc;
+
+	feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
+	if (feature_diag < 0)
+		return feature_diag;
 
 	device = dasd_create_device(cdev);
 	if (IS_ERR(device))
 		return PTR_ERR(device);
 
-	if (test_bit(DASD_FLAG_USE_DIAG, &device->flags)) {
+	if (feature_diag) {
 	  	if (!dasd_diag_discipline_pointer) {
 		        printk (KERN_WARNING
 				"dasd_generic couldn't online device %s "
diff --git a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c
index ed1ab47..4f365bf 100644
--- a/drivers/s390/block/dasd_cmb.c
+++ b/drivers/s390/block/dasd_cmb.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.6 $)
+ * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.9 $)
  *
  * Linux on zSeries Channel Measurement Facility support
  *  (dasd device driver interface)
@@ -23,7 +23,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #include <linux/init.h>
-#include <linux/ioctl32.h>
 #include <linux/module.h>
 #include <asm/ccwdev.h>
 #include <asm/cmb.h>
@@ -84,27 +83,13 @@
 static inline int
 ioctl_reg(unsigned int no, dasd_ioctl_fn_t handler)
 {
-	int ret;
-	ret = dasd_ioctl_no_register(THIS_MODULE, no, handler);
-#ifdef CONFIG_COMPAT
-	if (ret)
-		return ret;
-
-	ret = register_ioctl32_conversion(no, NULL);
-	if (ret)
-		dasd_ioctl_no_unregister(THIS_MODULE, no, handler);
-#endif
-	return ret;
+	return dasd_ioctl_no_register(THIS_MODULE, no, handler);
 }
 
 static inline void
 ioctl_unreg(unsigned int no, dasd_ioctl_fn_t handler)
 {
 	dasd_ioctl_no_unregister(THIS_MODULE, no, handler);
-#ifdef CONFIG_COMPAT
-	unregister_ioctl32_conversion(no);
-#endif
-
 }
 
 static void
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index ad1841a..1aedc48 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -11,7 +11,7 @@
  * functions may not be called from interrupt context. In particular
  * dasd_get_device is a no-no from interrupt context.
  *
- * $Revision: 1.37 $
+ * $Revision: 1.40 $
  */
 
 #include <linux/config.h>
@@ -513,14 +513,6 @@
 	if (!devmap->device) {
 		devmap->device = device;
 		device->devindex = devmap->devindex;
-		if (devmap->features & DASD_FEATURE_READONLY)
-			set_bit(DASD_FLAG_RO, &device->flags);
-		else
-			clear_bit(DASD_FLAG_RO, &device->flags);
-		if (devmap->features & DASD_FEATURE_USEDIAG)
-			set_bit(DASD_FLAG_USE_DIAG, &device->flags);
-		else
-			clear_bit(DASD_FLAG_USE_DIAG, &device->flags);
 		get_device(&cdev->dev);
 		device->cdev = cdev;
 		rc = 0;
@@ -651,14 +643,8 @@
 		devmap->features |= DASD_FEATURE_READONLY;
 	else
 		devmap->features &= ~DASD_FEATURE_READONLY;
-	if (devmap->device) {
-		if (devmap->device->gdp)
-			set_disk_ro(devmap->device->gdp, ro_flag);
-		if (ro_flag)
-			set_bit(DASD_FLAG_RO, &devmap->device->flags);
-		else
-			clear_bit(DASD_FLAG_RO, &devmap->device->flags);
-	}
+	if (devmap->device && devmap->device->gdp)
+		set_disk_ro(devmap->device->gdp, ro_flag);
 	spin_unlock(&dasd_devmap_lock);
 	return count;
 }
@@ -739,6 +725,45 @@
 	.attrs = dasd_attrs,
 };
 
+/*
+ * Return value of the specified feature.
+ */
+int
+dasd_get_feature(struct ccw_device *cdev, int feature)
+{
+	struct dasd_devmap *devmap;
+
+	devmap = dasd_find_busid(cdev->dev.bus_id);
+	if (IS_ERR(devmap))
+		return (int) PTR_ERR(devmap);
+
+	return ((devmap->features & feature) != 0);
+}
+
+/*
+ * Set / reset given feature.
+ * Flag indicates wether to set (!=0) or the reset (=0) the feature.
+ */
+int
+dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
+{
+	struct dasd_devmap *devmap;
+
+	devmap = dasd_find_busid(cdev->dev.bus_id);
+	if (IS_ERR(devmap))
+		return (int) PTR_ERR(devmap);
+
+	spin_lock(&dasd_devmap_lock);
+	if (flag)
+		devmap->features |= feature;
+	else
+		devmap->features &= ~feature;
+
+	spin_unlock(&dasd_devmap_lock);
+	return 0;
+}
+
+
 int
 dasd_add_sysfs_files(struct ccw_device *cdev)
 {
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 838aedf..811060e 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.69 $
+ * $Revision: 1.71 $
  */
 
 #include <linux/config.h>
@@ -1101,7 +1101,8 @@
 				if (dasd_eckd_cdl_special(blk_per_trk, recid)){
 					rcmd |= 0x8;
 					count = dasd_eckd_cdl_reclen(recid);
-					if (count < blksize)
+					if (count < blksize &&
+					    rq_data_dir(req) == READ)
 						memset(dst + count, 0xe5,
 						       blksize - count);
 				}
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 1d52db4..96c4934 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -9,7 +9,7 @@
  *
  * gendisk related functions for the dasd driver.
  *
- * $Revision: 1.48 $
+ * $Revision: 1.50 $
  */
 
 #include <linux/config.h>
@@ -31,12 +31,16 @@
 dasd_gendisk_alloc(struct dasd_device *device)
 {
 	struct gendisk *gdp;
-	int len;
+	int len, feature_ro;
 
 	/* Make sure the minor for this device exists. */
 	if (device->devindex >= DASD_PER_MAJOR)
 		return -EBUSY;
 
+	feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
+	if (feature_ro < 0)
+		return feature_ro;
+
 	gdp = alloc_disk(1 << DASD_PARTN_BITS);
 	if (!gdp)
 		return -ENOMEM;
@@ -71,7 +75,7 @@
 
  	sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
 
-	if (test_bit(DASD_FLAG_RO, &device->flags))
+	if (feature_ro)
 		set_disk_ro(gdp, 1);
 	gdp->private_data = device;
 	gdp->queue = device->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 4586e0e..a9f38b2 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.63 $
+ * $Revision: 1.64 $
  */
 
 #ifndef DASD_INT_H
@@ -329,8 +329,6 @@
 #define DASD_STOPPED_DC_EIO  16        /* disconnected, return -EIO */
 
 /* per device flags */
-#define DASD_FLAG_RO		0	/* device is read-only */
-#define DASD_FLAG_USE_DIAG	1	/* use diag disciplnie */
 #define DASD_FLAG_DSC_ERROR	2	/* return -EIO when disconnected */
 #define DASD_FLAG_OFFLINE	3	/* device is in offline processing */
 
@@ -501,6 +499,9 @@
 struct dasd_device *dasd_create_device(struct ccw_device *);
 void dasd_delete_device(struct dasd_device *);
 
+int dasd_get_feature(struct ccw_device *, int);
+int dasd_set_feature(struct ccw_device *, int, int);
+
 int dasd_add_sysfs_files(struct ccw_device *);
 void dasd_remove_sysfs_files(struct ccw_device *);
 
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index f1892ba..980c555 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -7,6 +7,8 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
+ * $Revision: 1.45 $
+ *
  * i/o controls for the dasd driver.
  */
 #include <linux/config.h>
@@ -294,6 +296,7 @@
 {
 	struct dasd_device *device;
 	struct format_data_t fdata;
+	int feature_ro;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -304,7 +307,11 @@
 
 	if (device == NULL)
 		return -ENODEV;
-	if (test_bit(DASD_FLAG_RO, &device->flags))
+
+	feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
+	if (feature_ro < 0)
+		return feature_ro;
+	if (feature_ro)
 		return -EROFS;
 	if (copy_from_user(&fdata, (void __user *) args,
 			   sizeof (struct format_data_t)))
@@ -377,7 +384,7 @@
 	struct dasd_device *device;
 	struct dasd_information2_t *dasd_info;
 	unsigned long flags;
-	int rc;
+	int rc, feature_ro;
 	struct ccw_device *cdev;
 
 	device = bdev->bd_disk->private_data;
@@ -387,6 +394,10 @@
 	if (!device->discipline->fill_info)
 		return -EINVAL;
 
+	feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
+	if (feature_ro < 0)
+		return feature_ro;
+
 	dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
 	if (dasd_info == NULL)
 		return -ENOMEM;
@@ -415,9 +426,8 @@
 	if ((device->state < DASD_STATE_READY) ||
 	    (dasd_check_blocksize(device->bp_block)))
 		dasd_info->format = DASD_FORMAT_NONE;
-	
-	dasd_info->features |= test_bit(DASD_FLAG_RO, &device->flags) ?
-		DASD_FEATURE_READONLY : DASD_FEATURE_DEFAULT;
+
+	dasd_info->features |= feature_ro;
 
 	if (device->discipline)
 		memcpy(dasd_info->type, device->discipline->name, 4);
@@ -460,7 +470,7 @@
 dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
 {
 	struct dasd_device *device;
-	int intval;
+	int intval, rc;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -472,12 +482,11 @@
 	device =  bdev->bd_disk->private_data;
 	if (device == NULL)
 		return -ENODEV;
+
 	set_disk_ro(bdev->bd_disk, intval);
-	if (intval)
-		set_bit(DASD_FLAG_RO, &device->flags);
-	else
-		clear_bit(DASD_FLAG_RO, &device->flags);
-	return 0;
+	rc = dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval);
+
+	return rc;
 }
 
 /*
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 353d411..d7f1974 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,7 +9,7 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.30 $
+ * $Revision: 1.31 $
  */
 
 #include <linux/config.h>
@@ -54,6 +54,7 @@
 {
 	struct dasd_device *device;
 	char *substr;
+	int feature;
 
 	device = dasd_device_from_devindex((unsigned long) v - 1);
 	if (IS_ERR(device))
@@ -77,7 +78,10 @@
 	else
 		seq_printf(m, " is ????????");
 	/* Print devices features. */
-	substr = test_bit(DASD_FLAG_RO, &device->flags) ? "(ro)" : " ";
+	feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
+	if (feature < 0)
+		return 0;
+	substr = feature ? "(ro)" : " ";
 	seq_printf(m, "%4s: ", substr);
 	/* Print device status information. */
 	switch ((device != NULL) ? device->state : -1) {
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 3720e77..83e6a06 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -45,7 +45,7 @@
 	else
 		ret = (cmpxchg(&adapter_handler, NULL, handler) ? -EBUSY : 0);
 	if (!ret)
-		synchronize_kernel();
+		synchronize_sched();  /* Allow interrupts to complete. */
 
 	sprintf (dbf_txt, "ret:%d", ret);
 	CIO_TRACE_EVENT (4, dbf_txt);
@@ -65,7 +65,7 @@
 		ret = -EINVAL;
 	else {
 		adapter_handler = NULL;
-		synchronize_kernel();
+		synchronize_sched();  /* Allow interrupts to complete. */
 		ret = 0;
 	}
 	sprintf (dbf_txt, "ret:%d", ret);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 99ce5a5..1d9b3f1 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.131 $
+ *   $Revision: 1.133 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -228,7 +228,7 @@
 int
 cio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm)
 {
-	return cio_start_key(sch, cpa, lpm, default_storage_key);
+	return cio_start_key(sch, cpa, lpm, PAGE_DEFAULT_KEY);
 }
 
 /*
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 11e260e..02d01a0 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device_ops.c
  *
- *   $Revision: 1.55 $
+ *   $Revision: 1.56 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -128,7 +128,7 @@
 		 unsigned long intparm, __u8 lpm, unsigned long flags)
 {
 	return ccw_device_start_key(cdev, cpa, intparm, lpm,
-				    default_storage_key, flags);
+				    PAGE_DEFAULT_KEY, flags);
 }
 
 int
@@ -137,7 +137,7 @@
 			 int expires)
 {
 	return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm,
-					    default_storage_key, flags,
+					    PAGE_DEFAULT_KEY, flags,
 					    expires);
 }
 
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 9ad14db..b6daada 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -1,7 +1,9 @@
 #ifndef _CIO_QDIO_H
 #define _CIO_QDIO_H
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.26 $"
+#include <asm/page.h>
+
+#define VERSION_CIO_QDIO_H "$Revision: 1.32 $"
 
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_VERBOSE_LEVEL 9
@@ -42,7 +44,7 @@
 
 #define QDIO_Q_LAPS 5
 
-#define QDIO_STORAGE_KEY 0
+#define QDIO_STORAGE_KEY PAGE_DEFAULT_KEY
 
 #define L2_CACHELINE_SIZE 256
 #define INDICATORS_PER_CACHELINE (L2_CACHELINE_SIZE/sizeof(__u32))
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index a98c00c..9ec29bb 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -385,8 +385,8 @@
 static ssize_t z90crypt_read(struct file *, char __user *, size_t, loff_t *);
 static ssize_t z90crypt_write(struct file *, const char __user *,
 							size_t, loff_t *);
-static int z90crypt_ioctl(struct inode *, struct file *,
-			  unsigned int, unsigned long);
+static long z90crypt_unlocked_ioctl(struct file *, unsigned int, unsigned long);
+static long z90crypt_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 static void z90crypt_reader_task(unsigned long);
 static void z90crypt_schedule_reader_task(unsigned long);
@@ -433,12 +433,15 @@
 static atomic_t z90crypt_step;
 
 static struct file_operations z90crypt_fops = {
-	.owner	 = THIS_MODULE,
-	.read	 = z90crypt_read,
-	.write	 = z90crypt_write,
-	.ioctl	 = z90crypt_ioctl,
-	.open	 = z90crypt_open,
-	.release = z90crypt_release
+	.owner		= THIS_MODULE,
+	.read		= z90crypt_read,
+	.write		= z90crypt_write,
+	.unlocked_ioctl	= z90crypt_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= z90crypt_compat_ioctl,
+#endif
+	.open		= z90crypt_open,
+	.release	= z90crypt_release
 };
 
 #ifndef Z90CRYPT_USE_HOTPLUG
@@ -474,14 +477,13 @@
 	compat_uptr_t	n_modulus;
 };
 
-static int
-trans_modexpo32(unsigned int fd, unsigned int cmd, unsigned long arg,
-		struct file *file)
+static long
+trans_modexpo32(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct ica_rsa_modexpo_32 __user *mex32u = compat_ptr(arg);
 	struct ica_rsa_modexpo_32  mex32k;
 	struct ica_rsa_modexpo __user *mex64;
-	int ret = 0;
+	long ret = 0;
 	unsigned int i;
 
 	if (!access_ok(VERIFY_WRITE, mex32u, sizeof(struct ica_rsa_modexpo_32)))
@@ -498,7 +500,7 @@
 	    __put_user(compat_ptr(mex32k.b_key), &mex64->b_key)           ||
 	    __put_user(compat_ptr(mex32k.n_modulus), &mex64->n_modulus))
 		return -EFAULT;
-	ret = sys_ioctl(fd, cmd, (unsigned long)mex64);
+	ret = z90crypt_unlocked_ioctl(filp, cmd, (unsigned long)mex64);
 	if (!ret)
 		if (__get_user(i, &mex64->outputdatalength) ||
 		    __put_user(i, &mex32u->outputdatalength))
@@ -518,14 +520,13 @@
 	compat_uptr_t	u_mult_inv;
 };
 
-static int
-trans_modexpo_crt32(unsigned int fd, unsigned int cmd, unsigned long arg,
-		    struct file *file)
+static long
+trans_modexpo_crt32(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct ica_rsa_modexpo_crt_32 __user *crt32u = compat_ptr(arg);
 	struct ica_rsa_modexpo_crt_32  crt32k;
 	struct ica_rsa_modexpo_crt __user *crt64;
-	int ret = 0;
+	long ret = 0;
 	unsigned int i;
 
 	if (!access_ok(VERIFY_WRITE, crt32u,
@@ -546,9 +547,8 @@
 	    __put_user(compat_ptr(crt32k.np_prime), &crt64->np_prime)     ||
 	    __put_user(compat_ptr(crt32k.nq_prime), &crt64->nq_prime)     ||
 	    __put_user(compat_ptr(crt32k.u_mult_inv), &crt64->u_mult_inv))
-		ret = -EFAULT;
-	if (!ret)
-		ret = sys_ioctl(fd, cmd, (unsigned long)crt64);
+		return -EFAULT;
+	ret = z90crypt_unlocked_ioctl(filp, cmd, (unsigned long)crt64);
 	if (!ret)
 		if (__get_user(i, &crt64->outputdatalength) ||
 		    __put_user(i, &crt32u->outputdatalength))
@@ -556,66 +556,34 @@
 	return ret;
 }
 
-static int compatible_ioctls[] = {
-	ICAZ90STATUS, Z90QUIESCE, Z90STAT_TOTALCOUNT, Z90STAT_PCICACOUNT,
-	Z90STAT_PCICCCOUNT, Z90STAT_PCIXCCCOUNT, Z90STAT_PCIXCCMCL2COUNT,
-	Z90STAT_PCIXCCMCL3COUNT, Z90STAT_CEX2CCOUNT, Z90STAT_REQUESTQ_COUNT,
-	Z90STAT_PENDINGQ_COUNT, Z90STAT_TOTALOPEN_COUNT, Z90STAT_DOMAIN_INDEX,
-	Z90STAT_STATUS_MASK, Z90STAT_QDEPTH_MASK, Z90STAT_PERDEV_REQCNT,
-};
-
-static void z90_unregister_ioctl32s(void)
+static long
+z90crypt_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	int i;
-
-	unregister_ioctl32_conversion(ICARSAMODEXPO);
-	unregister_ioctl32_conversion(ICARSACRT);
-
-	for(i = 0; i < ARRAY_SIZE(compatible_ioctls); i++)
-		unregister_ioctl32_conversion(compatible_ioctls[i]);
-}
-
-static int z90_register_ioctl32s(void)
-{
-	int result, i;
-
-	result = register_ioctl32_conversion(ICARSAMODEXPO, trans_modexpo32);
-	if (result == -EBUSY) {
-		unregister_ioctl32_conversion(ICARSAMODEXPO);
-		result = register_ioctl32_conversion(ICARSAMODEXPO,
-						     trans_modexpo32);
-	}
-	if (result)
-		return result;
-	result = register_ioctl32_conversion(ICARSACRT, trans_modexpo_crt32);
-	if (result == -EBUSY) {
-		unregister_ioctl32_conversion(ICARSACRT);
-		result = register_ioctl32_conversion(ICARSACRT,
-						     trans_modexpo_crt32);
-	}
-	if (result)
-		return result;
-
-	for(i = 0; i < ARRAY_SIZE(compatible_ioctls); i++) {
-		result = register_ioctl32_conversion(compatible_ioctls[i], 0);
-		if (result == -EBUSY) {
-			unregister_ioctl32_conversion(compatible_ioctls[i]);
-			result = register_ioctl32_conversion(
-						       compatible_ioctls[i], 0);
-		}
-		if (result)
-			return result;
-	}
-	return 0;
-}
-#else // !CONFIG_COMPAT
-static inline void z90_unregister_ioctl32s(void)
-{
-}
-
-static inline int z90_register_ioctl32s(void)
-{
-	return 0;
+	switch (cmd) {
+	case ICAZ90STATUS:
+	case Z90QUIESCE:
+	case Z90STAT_TOTALCOUNT:
+	case Z90STAT_PCICACOUNT:
+	case Z90STAT_PCICCCOUNT:
+	case Z90STAT_PCIXCCCOUNT:
+	case Z90STAT_PCIXCCMCL2COUNT:
+	case Z90STAT_PCIXCCMCL3COUNT:
+	case Z90STAT_CEX2CCOUNT:
+	case Z90STAT_REQUESTQ_COUNT:
+	case Z90STAT_PENDINGQ_COUNT:
+	case Z90STAT_TOTALOPEN_COUNT:
+	case Z90STAT_DOMAIN_INDEX:
+	case Z90STAT_STATUS_MASK:
+	case Z90STAT_QDEPTH_MASK:
+	case Z90STAT_PERDEV_REQCNT:
+		return z90crypt_unlocked_ioctl(filp, cmd, arg);
+	case ICARSAMODEXPO:
+		return trans_modexpo32(filp, cmd, arg);
+	case ICARSACRT:
+		return trans_modexpo_crt32(filp, cmd, arg);
+	default:
+		return -ENOIOCTLCMD;
+  	}
 }
 #endif
 
@@ -730,14 +698,9 @@
 	reader_timer.expires = jiffies + (READERTIME * HZ / 1000);
 	add_timer(&reader_timer);
 
-	if ((result = z90_register_ioctl32s()))
-		goto init_module_cleanup;
-
 	return 0; // success
 
 init_module_cleanup:
-	z90_unregister_ioctl32s();
-
 #ifndef Z90CRYPT_USE_HOTPLUG
 	if ((nresult = misc_deregister(&z90crypt_misc_device)))
 		PRINTK("misc_deregister failed with %d.\n", nresult);
@@ -763,8 +726,6 @@
 
 	PDEBUG("PID %d\n", PID());
 
-	z90_unregister_ioctl32s();
-
 	remove_proc_entry("driver/z90crypt", 0);
 
 #ifndef Z90CRYPT_USE_HOTPLUG
@@ -800,7 +761,7 @@
  *     z90crypt_release
  *     z90crypt_read
  *     z90crypt_write
- *     z90crypt_ioctl
+ *     z90crypt_unlocked_ioctl
  *     z90crypt_status
  *     z90crypt_status_write
  *	 disable_card
@@ -1804,9 +1765,8 @@
  * This function is a little long, but it's really just one large switch
  * statement.
  */
-static int
-z90crypt_ioctl(struct inode *inode, struct file *filp,
-	       unsigned int cmd, unsigned long arg)
+static long
+z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct priv_data *private_data_p = filp->private_data;
 	unsigned char *status;
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index a3d2858..1e3f7f3 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -32,7 +32,7 @@
 	struct list_head list;
 	char *prefix;
 	int len;
-	void (*callback)(char *str);
+	void (*callback)(char *from, char *str);
 };
 
 MODULE_AUTHOR
@@ -55,8 +55,9 @@
 {
 	struct smsg_callback *cb;
 	unsigned char *msg;
+	unsigned char sender[9];
 	unsigned short len;
-	int rc;
+	int rc, i;
 
 	len = eib->ln1msg2.ipbfln1f;
 	msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA);
@@ -69,10 +70,18 @@
 	if (rc == 0) {
 		msg[len] = 0;
 		EBCASC(msg, len);
+		memcpy(sender, msg, 8);
+		sender[8] = 0;
+		/* Remove trailing whitespace from the sender name. */
+		for (i = 7; i >= 0; i--) {
+			if (sender[i] != ' ' && sender[i] != '\t')
+				break;
+			sender[i] = 0;
+		}
 		spin_lock(&smsg_list_lock);
 		list_for_each_entry(cb, &smsg_list, list)
 			if (strncmp(msg + 8, cb->prefix, cb->len) == 0) {
-				cb->callback(msg + 8);
+				cb->callback(sender, msg + 8);
 				break;
 			}
 		spin_unlock(&smsg_list_lock);
@@ -91,7 +100,7 @@
 };
 
 int
-smsg_register_callback(char *prefix, void (*callback)(char *str))
+smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
 {
 	struct smsg_callback *cb;
 
@@ -108,7 +117,7 @@
 }
 
 void
-smsg_unregister_callback(char *prefix, void (*callback)(char *str))
+smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
 {
 	struct smsg_callback *cb, *tmp;
 
diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h
index 04cd871..67f5d4f 100644
--- a/drivers/s390/net/smsgiucv.h
+++ b/drivers/s390/net/smsgiucv.h
@@ -5,6 +5,6 @@
  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
-int  smsg_register_callback(char *, void (*)(char *));
-void smsg_unregister_callback(char *, void (*)(char *));
+int  smsg_register_callback(char *, void (*)(char *, char *));
+void smsg_unregister_callback(char *, void (*)(char *, char *));
 
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index bf3273e..9b988ba 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -28,10 +28,46 @@
 
 static int rtc_busy = 0;
 
+/* This is the structure layout used by drivers/char/rtc.c, we
+ * support that driver's ioctls so that things are less messy in
+ * userspace.
+ */
+struct rtc_time_generic {
+	int tm_sec;
+	int tm_min;
+	int tm_hour;
+	int tm_mday;
+	int tm_mon;
+	int tm_year;
+	int tm_wday;
+	int tm_yday;
+	int tm_isdst;
+};
+#define RTC_AIE_ON	_IO('p', 0x01)	/* Alarm int. enable on		*/
+#define RTC_AIE_OFF	_IO('p', 0x02)	/* ... off			*/
+#define RTC_UIE_ON	_IO('p', 0x03)	/* Update int. enable on	*/
+#define RTC_UIE_OFF	_IO('p', 0x04)	/* ... off			*/
+#define RTC_PIE_ON	_IO('p', 0x05)	/* Periodic int. enable on	*/
+#define RTC_PIE_OFF	_IO('p', 0x06)	/* ... off			*/
+#define RTC_WIE_ON	_IO('p', 0x0f)  /* Watchdog int. enable on	*/
+#define RTC_WIE_OFF	_IO('p', 0x10)  /* ... off			*/
+#define RTC_RD_TIME	_IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time   */
+#define RTC_SET_TIME	_IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time    */
+#define RTC_ALM_SET	_IOW('p', 0x07, struct rtc_time) /* Set alarm time  */
+#define RTC_ALM_READ	_IOR('p', 0x08, struct rtc_time) /* Read alarm time */
+#define RTC_IRQP_READ	_IOR('p', 0x0b, unsigned long)	 /* Read IRQ rate   */
+#define RTC_IRQP_SET	_IOW('p', 0x0c, unsigned long)	 /* Set IRQ rate    */
+#define RTC_EPOCH_READ	_IOR('p', 0x0d, unsigned long)	 /* Read epoch      */
+#define RTC_EPOCH_SET	_IOW('p', 0x0e, unsigned long)	 /* Set epoch       */
+#define RTC_WKALM_SET	_IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/
+#define RTC_WKALM_RD	_IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/
+#define RTC_PLL_GET	_IOR('p', 0x11, struct rtc_pll_info)  /* Get PLL correction */
+#define RTC_PLL_SET	_IOW('p', 0x12, struct rtc_pll_info)  /* Set PLL correction */
+
 /* Retrieve the current date and time from the real time clock. */
 static void get_rtc_time(struct rtc_time *t)
 {
-	void * __iomem regs = mstk48t02_regs;
+	void __iomem *regs = mstk48t02_regs;
 	u8 tmp;
 
 	spin_lock_irq(&mostek_lock);
@@ -58,7 +94,7 @@
 /* Set the current date and time inthe real time clock. */
 void set_rtc_time(struct rtc_time *t)
 {
-	void * __iomem regs = mstk48t02_regs;
+	void __iomem *regs = mstk48t02_regs;
 	u8 tmp;
 
 	spin_lock_irq(&mostek_lock);
@@ -82,29 +118,87 @@
 	spin_unlock_irq(&mostek_lock);
 }
 
+static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm)
+{
+	struct rtc_time_generic __user *utm = argp;
+
+	if (__put_user(tm->sec, &utm->tm_sec) ||
+	    __put_user(tm->min, &utm->tm_min) ||
+	    __put_user(tm->hour, &utm->tm_hour) ||
+	    __put_user(tm->dom, &utm->tm_mday) ||
+	    __put_user(tm->month, &utm->tm_mon) ||
+	    __put_user(tm->year, &utm->tm_year) ||
+	    __put_user(tm->dow, &utm->tm_wday) ||
+	    __put_user(0, &utm->tm_yday) ||
+	    __put_user(0, &utm->tm_isdst))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp)
+{
+	struct rtc_time_generic __user *utm = argp;
+
+	if (__get_user(tm->sec, &utm->tm_sec) ||
+	    __get_user(tm->min, &utm->tm_min) ||
+	    __get_user(tm->hour, &utm->tm_hour) ||
+	    __get_user(tm->dom, &utm->tm_mday) ||
+	    __get_user(tm->month, &utm->tm_mon) ||
+	    __get_user(tm->year, &utm->tm_year) ||
+	    __get_user(tm->dow, &utm->tm_wday))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
 	struct rtc_time rtc_tm;
 	void __user *argp = (void __user *)arg;
 
-	switch (cmd)
-	{
+	switch (cmd) {
+	/* No interrupt support, return an error
+	 * compatible with drivers/char/rtc.c
+	 */
+	case RTC_AIE_OFF:
+	case RTC_AIE_ON:
+	case RTC_PIE_OFF:
+	case RTC_PIE_ON:
+	case RTC_UIE_OFF:
+	case RTC_UIE_ON:
+	case RTC_IRQP_READ:
+	case RTC_IRQP_SET:
+	case RTC_EPOCH_SET:
+	case RTC_EPOCH_READ:
+		return -EINVAL;
+
 	case RTCGET:
+	case RTC_RD_TIME:
 		memset(&rtc_tm, 0, sizeof(struct rtc_time));
 		get_rtc_time(&rtc_tm);
 
-		if (copy_to_user(argp, &rtc_tm, sizeof(struct rtc_time)))
+		if (cmd == RTCGET) {
+			if (copy_to_user(argp, &rtc_tm,
+					 sizeof(struct rtc_time)))
+				return -EFAULT;
+		} else if (put_rtc_time_generic(argp, &rtc_tm))
 			return -EFAULT;
 
 		return 0;
 
 
 	case RTCSET:
+	case RTC_SET_TIME:
 		if (!capable(CAP_SYS_TIME))
 			return -EPERM;
 
-		if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time)))
+		if (cmd == RTCSET) {
+			if (copy_from_user(&rtc_tm, argp,
+					   sizeof(struct rtc_time)))
+				return -EFAULT;
+		} else if (get_rtc_time_generic(&rtc_tm, argp))
 			return -EFAULT;
 
 		set_rtc_time(&rtc_tm);
@@ -156,7 +250,7 @@
 	/* It is possible we are being driven by some other RTC chip
 	 * and thus another RTC driver is handling things.
 	 */
-	if (mstk48t02_regs == 0)
+	if (!mstk48t02_regs)
 		return -ENODEV;
 
 	error = misc_register(&rtc_dev);
@@ -164,6 +258,7 @@
 		printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n");
 		return error;
 	}
+	printk("rtc_sun_init: Registered Mostek RTC driver.\n");
 
 	return 0;
 }
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index ba88be3..88e3409 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -278,7 +278,7 @@
 
 config SCSI_7000FASST
 	tristate "7000FASST SCSI support"
-	depends on ISA && SCSI
+	depends on ISA && SCSI && ISA_DMA_API
 	help
 	  This driver supports the Western Digital 7000 SCSI host adapter
 	  family.  Some information is in the source:
@@ -313,7 +313,7 @@
 
 config SCSI_AHA1542
 	tristate "Adaptec AHA1542 support"
-	depends on ISA && SCSI
+	depends on ISA && SCSI && ISA_DMA_API
 	---help---
 	  This is support for a SCSI host adapter.  It is explained in section
 	  3.4 of the SCSI-HOWTO, available from
@@ -533,7 +533,7 @@
 
 config SCSI_BUSLOGIC
 	tristate "BusLogic SCSI support"
-	depends on (PCI || ISA || MCA) && SCSI && (BROKEN || !SPARC64)
+	depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
 	---help---
 	  This is support for BusLogic MultiMaster and FlashPoint SCSI Host
 	  Adapters. Consult the SCSI-HOWTO, available from
@@ -589,7 +589,7 @@
 
 config SCSI_EATA
 	tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support"
-	depends on (ISA || EISA || PCI) && SCSI && (BROKEN || !SPARC64)
+	depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
 	---help---
 	  This driver supports all EATA/DMA-compliant SCSI host adapters.  DPT
 	  ISA and all EISA I/O addresses are probed looking for the "EATA"
@@ -683,7 +683,7 @@
 
 config SCSI_GDTH
 	tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support"
-	depends on (ISA || EISA || PCI) && SCSI && (BROKEN || !SPARC64)
+	depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
 	---help---
 	  Formerly called GDT SCSI Disk Array Controller Support.
 
@@ -1412,7 +1412,7 @@
 
 config SCSI_U14_34F
 	tristate "UltraStor 14F/34F support"
-	depends on ISA && SCSI
+	depends on ISA && SCSI && ISA_DMA_API
 	---help---
 	  This is support for the UltraStor 14F and 34F SCSI-2 host adapters.
 	  The source at <file:drivers/scsi/u14-34f.c> contains some
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 74293f6..064781a 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -1824,7 +1824,10 @@
 		/* loop */
 		while (hmuch) {
 			int j, fifo_stuck = 0, newphase;
-			unsigned long flags, timeout;
+			unsigned long timeout;
+#if 0
+			unsigned long flags;
+#endif
 #if 0
 			if ( i % 10 )
 				ESPDATA(("\r"));
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 7e9e6b3..5fd8f3e 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -450,7 +450,7 @@
 		}
 	}
 
-	return 0;
+	return err;
 }
 
 /**
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index d8ab73b..f690053 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -49,6 +49,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
+#define DRV_VERSION "1.101"
+
 #define DEBUG_ESP
 /* #define DEBUG_ESP_HME */
 /* #define DEBUG_ESP_DATA */
@@ -1145,7 +1147,7 @@
 	static struct sbus_dev esp_dev;
 	int esps_in_use = 0;
 
-	espchain = 0;
+	espchain = NULL;
 
 	if (sun4_esp_physaddr) {
 		memset (&esp_dev, 0, sizeof(esp_dev));
@@ -2511,7 +2513,7 @@
 		ESPLOG(("esp%d: Weird, being reselected but disconnected "
 			"command queue is empty.\n", esp->esp_id));
 	esp->snip = 0;
-	esp->current_SC = 0;
+	esp->current_SC = NULL;
 	sp->SCp.phase = not_issued;
 	append_SC(&esp->issue_SC, sp);
 }
@@ -4146,7 +4148,7 @@
 }
 
 static espfunc_t isvc_vector[] = {
-	0,
+	NULL,
 	esp_do_phase_determine,
 	esp_do_resetbus,
 	esp_finish_reset,
@@ -4398,5 +4400,8 @@
 
 #include "scsi_module.c"
 
+MODULE_DESCRIPTION("EnhancedScsiProcessor Sun SCSI driver");
+MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index e70dedb..7976947 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -137,7 +137,7 @@
 static int pas16_irq = 0;
  
 
-int scsi_irq_translate[] =
+static const int scsi_irq_translate[] =
 	{ 0,  0,  1,  2,  3,  4,  5,  6, 0,  0,  7,  8,  9,  0, 10, 11 };
 
 /* The default_irqs array contains values used to set the irq into the
@@ -145,7 +145,7 @@
  * irq jumpers on the board).  The first value in the array will be
  * assigned to logical board 0, the next to board 1, etc.
  */
-int default_irqs[] __initdata = 
+static int default_irqs[] __initdata =
 	{  PAS16_DEFAULT_BOARD_1_IRQ,
 	   PAS16_DEFAULT_BOARD_2_IRQ,
 	   PAS16_DEFAULT_BOARD_3_IRQ,
@@ -177,7 +177,7 @@
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 
-unsigned short  pas16_offset[ 8 ] =
+static const unsigned short  pas16_offset[ 8 ] =
     {
 	0x1c00,    /* OUTPUT_DATA_REG */
 	0x1c01,    /* INITIATOR_COMMAND_REG */
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 7bb0a2e..c01b719 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -45,7 +45,7 @@
 	Scsi_Cmnd cmd;
 	char inquiry[256];
 	fc_channel *fc;
-} *fcs __initdata = { 0 };
+} *fcs __initdata;
 static int fcscount __initdata = 0;
 static atomic_t fcss __initdata = ATOMIC_INIT(0);
 DECLARE_MUTEX_LOCKED(fc_sem);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 0d730f6..5578ae9 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -542,7 +542,7 @@
 		 * that the device is no longer present */
 		cmd->result = DID_NO_CONNECT << 16;
 		atomic_inc(&cmd->device->iorequest_cnt);
-		scsi_done(cmd);
+		__scsi_done(cmd);
 		/* return 0 (because the command has been processed) */
 		goto out;
 	}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 1035585..cb789c35 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -582,7 +582,7 @@
 
 	memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
 
-	scsi_result = kmalloc(252, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0);
+	scsi_result = kmalloc(252, GFP_ATOMIC | ((scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0));
 
 
 	if (unlikely(!scsi_result)) {
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 287d197..cca7726 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -801,7 +801,7 @@
 	if (!sreq)
 		goto out_free_sdev;
 	result = kmalloc(256, GFP_ATOMIC |
-			(shost->unchecked_isa_dma) ? __GFP_DMA : 0);
+			((shost->unchecked_isa_dma) ? __GFP_DMA : 0));
 	if (!result)
 		goto out_free_sreq;
 
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 303d765..28966d0 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/workqueue.h>
+#include <linux/blkdev.h>
 #include <asm/semaphore.h>
 #include <scsi/scsi.h>
 #include "scsi_priv.h"
@@ -41,6 +42,11 @@
 
 #define SPI_MAX_ECHO_BUFFER_SIZE	4096
 
+#define DV_LOOPS	3
+#define DV_TIMEOUT	(10*HZ)
+#define DV_RETRIES	3	/* should only need at most 
+				 * two cc/ua clears */
+
 /* Private data accessors (keep these out of the header file) */
 #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
 #define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem)
@@ -100,6 +106,29 @@
 	return result;
 }
 
+/* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions
+ * resulting from (likely) bus and device resets */
+static void spi_wait_req(struct scsi_request *sreq, const void *cmd,
+			 void *buffer, unsigned bufflen)
+{
+	int i;
+
+	for(i = 0; i < DV_RETRIES; i++) {
+		sreq->sr_request->flags |= REQ_FAILFAST;
+
+		scsi_wait_req(sreq, cmd, buffer, bufflen,
+			      DV_TIMEOUT, /* retries */ 1);
+		if (sreq->sr_result & DRIVER_SENSE) {
+			struct scsi_sense_hdr sshdr;
+
+			if (scsi_request_normalize_sense(sreq, &sshdr)
+			    && sshdr.sense_key == UNIT_ATTENTION)
+				continue;
+		}
+		break;
+	}
+}
+
 static struct {
 	enum spi_signal_type	value;
 	char			*name;
@@ -378,11 +407,6 @@
 	if(i->f->set_##x)		\
 		i->f->set_##x(sdev->sdev_target, y)
 
-#define DV_LOOPS	3
-#define DV_TIMEOUT	(10*HZ)
-#define DV_RETRIES	3	/* should only need at most 
-				 * two cc/ua clears */
-
 enum spi_compare_returns {
 	SPI_COMPARE_SUCCESS,
 	SPI_COMPARE_FAILURE,
@@ -446,8 +470,7 @@
 	for (r = 0; r < retries; r++) {
 		sreq->sr_cmd_len = 0;	/* wait_req to fill in */
 		sreq->sr_data_direction = DMA_TO_DEVICE;
-		scsi_wait_req(sreq, spi_write_buffer, buffer, len,
-			      DV_TIMEOUT, DV_RETRIES);
+		spi_wait_req(sreq, spi_write_buffer, buffer, len);
 		if(sreq->sr_result || !scsi_device_online(sdev)) {
 			struct scsi_sense_hdr sshdr;
 
@@ -471,8 +494,7 @@
 		memset(ptr, 0, len);
 		sreq->sr_cmd_len = 0;	/* wait_req to fill in */
 		sreq->sr_data_direction = DMA_FROM_DEVICE;
-		scsi_wait_req(sreq, spi_read_buffer, ptr, len,
-			      DV_TIMEOUT, DV_RETRIES);
+		spi_wait_req(sreq, spi_read_buffer, ptr, len);
 		scsi_device_set_state(sdev, SDEV_QUIESCE);
 
 		if (memcmp(buffer, ptr, len) != 0)
@@ -500,8 +522,7 @@
 
 		memset(ptr, 0, len);
 
-		scsi_wait_req(sreq, spi_inquiry, ptr, len,
-			      DV_TIMEOUT, DV_RETRIES);
+		spi_wait_req(sreq, spi_inquiry, ptr, len);
 		
 		if(sreq->sr_result || !scsi_device_online(sdev)) {
 			scsi_device_set_state(sdev, SDEV_QUIESCE);
@@ -593,8 +614,7 @@
 	 * (reservation conflict, device not ready, etc) just
 	 * skip the write tests */
 	for (l = 0; ; l++) {
-		scsi_wait_req(sreq, spi_test_unit_ready, NULL, 0,
-			      DV_TIMEOUT, DV_RETRIES);
+		spi_wait_req(sreq, spi_test_unit_ready, NULL, 0);
 
 		if(sreq->sr_result) {
 			if(l >= 3)
@@ -608,8 +628,7 @@
 	sreq->sr_cmd_len = 0;
 	sreq->sr_data_direction = DMA_FROM_DEVICE;
 
-	scsi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4,
-		      DV_TIMEOUT, DV_RETRIES);
+	spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4);
 
 	if (sreq->sr_result)
 		/* Device has no echo buffer */
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 5ff83d2..5b07c6e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -2038,8 +2038,9 @@
 	struct sym_hcb *np = sym_get_hcb(shost);
 	struct sym_tcb *tp = &np->target[starget->id];
 
-	/* have to have DT for these transfers */
-	if (period <= np->minsync)
+	/* have to have DT for these transfers, but DT will also
+	 * set width, so check that this is allowed */
+	if (period <= np->minsync && spi_width(starget))
 		tp->tgoal.dt = 1;
 
 	tp->tgoal.period = period;
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index f8504b0..33fbda7 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -110,7 +110,7 @@
 		port->icount.rx++;
 
 		rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
-		if (rxs & RXSTAT_ANYERR) {
+		if (unlikely(rxs & RXSTAT_ANYERR)) {
 			if (rxs & RXSTAT_PARITY)
 				port->icount.parity++;
 			else if (rxs & RXSTAT_FRAME)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 218b693..0d93586 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -51,7 +51,7 @@
  *   share_irqs - whether we pass SA_SHIRQ to request_irq().  This option
  *                is unsafe when used on edge-triggered interrupts.
  */
-unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
+static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
 
 /*
  * Debugging.
diff --git a/drivers/serial/8250_hp300.c b/drivers/serial/8250_hp300.c
index b8d51eb..4315afe 100644
--- a/drivers/serial/8250_hp300.c
+++ b/drivers/serial/8250_hp300.c
@@ -9,15 +9,15 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/tty.h>
 #include <linux/serial.h>
-#include <linux/serialP.h>
 #include <linux/serial_core.h>
 #include <linux/delay.h>
 #include <linux/dio.h>
 #include <linux/console.h>
 #include <asm/io.h>
 
+#include "8250.h"
+
 #if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
 #warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
 #endif
@@ -163,7 +163,7 @@
 static int __devinit hpdca_init_one(struct dio_dev *d,
                                 const struct dio_device_id *ent)
 {
-	struct serial_struct serial_req;
+	struct uart_port port;
 	int line;
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -172,21 +172,22 @@
 		return 0;
 	}
 #endif
-	memset(&serial_req, 0, sizeof(struct serial_struct));
+	memset(&port, 0, sizeof(struct uart_port));
 
 	/* Memory mapped I/O */
-	serial_req.io_type = SERIAL_IO_MEM;
-	serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
-	serial_req.irq = d->ipl;
-	serial_req.baud_base = HPDCA_BAUD_BASE;
-	serial_req.iomap_base = (d->resource.start + UART_OFFSET);
-	serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
-	serial_req.iomem_reg_shift = 1;
-	line = register_serial(&serial_req);
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+	port.irq = d->ipl;
+	port.uartclk = HPDCA_BAUD_BASE * 16;
+	port.mapbase = (d->resource.start + UART_OFFSET);
+	port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
+	port.regshift = 1;
+	port.dev = &d->dev;
+	line = serial8250_register_port(&port);
 
 	if (line < 0) {
 		printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
-		       " irq %d failed\n", d->scode, serial_req.irq);
+		       " irq %d failed\n", d->scode, port.irq);
 		return -ENOMEM;
 	}
 
@@ -209,7 +210,7 @@
 #ifdef CONFIG_HPAPCI
 	int line;
 	unsigned long base;
-	struct serial_struct serial_req;
+	struct uart_port uport;
 	struct hp300_port *port;
 	int i;
 #endif
@@ -251,25 +252,25 @@
 		if (!port)
 			return -ENOMEM;
 
-		memset(&serial_req, 0, sizeof(struct serial_struct));
+		memset(&uport, 0, sizeof(struct uart_port));
 
 		base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
 
 		/* Memory mapped I/O */
-		serial_req.io_type = SERIAL_IO_MEM;
-		serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+		uport.iotype = UPIO_MEM;
+		uport.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
 		/* XXX - no interrupt support yet */
-		serial_req.irq = 0;
-		serial_req.baud_base = HPAPCI_BAUD_BASE;
-		serial_req.iomap_base = base;
-		serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
-		serial_req.iomem_reg_shift = 2;
+		uport.irq = 0;
+		uport.uartclk = HPAPCI_BAUD_BASE * 16;
+		uport.mapbase = base;
+		uport.membase = (char *)(base + DIO_VIRADDRBASE);
+		uport.regshift = 2;
 
-		line = register_serial(&serial_req);
+		line = serial8250_register_port(&uport);
 
 		if (line < 0) {
 			printk(KERN_NOTICE "8250_hp300: register_serial() APCI %d"
-			       " irq %d failed\n", i, serial_req.irq);
+			       " irq %d failed\n", i, uport.irq);
 			kfree(port);
 			continue;
 		}
@@ -299,7 +300,7 @@
 		/* Disable board-interrupts */
 		out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
 	}
-	unregister_serial(line);
+	serial8250_unregister_port(line);
 }
 #endif
 
@@ -309,7 +310,7 @@
 	struct hp300_port *port, *to_free;
 
 	for (port = hp300_ports; port; ) {
-		unregister_serial(port->line);
+		serial8250_unregister_port(port->line);
 		to_free = port;
 		port = port->next;
 		kfree(to_free);
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index f8d90d0..de54bdc 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1009,6 +1009,8 @@
  *  n    = number of serial ports
  *  baud = baud rate
  *
+ * This table is sorted by (in order): baud, bt, bn, n.
+ *
  * Please note: in theory if n = 1, _bt infix should make no difference.
  * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
  */
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 484f6fb..f2a5e29 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -172,7 +172,7 @@
 		 * out of the main execution path
 		 */
 		rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
-		if (rsr & UART01x_RSR_ANY) {
+		if (unlikely(rsr & UART01x_RSR_ANY)) {
 			if (rsr & UART01x_RSR_BE) {
 				rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
 				port->icount.brk++;
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index ff658a8..d5cbef3 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -137,7 +137,7 @@
 		 * out of the main execution path
 		 */
 		rsr = readw(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
-		if (rsr & UART01x_RSR_ANY) {
+		if (unlikely(rsr & UART01x_RSR_ANY)) {
 			if (rsr & UART01x_RSR_BE) {
 				rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
 				uap->port.icount.brk++;
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 16592fa..6242f30 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -116,54 +116,43 @@
 		 * Note that the error handling code is
 		 * out of the main execution path
 		 */
-		if (ch & UART_ANY_ERR)
-			goto handle_error;
+		if (unlikely(ch & UART_ANY_ERR)) {
+			if (ch & UARTDR_PARERR)
+				port->icount.parity++;
+			else if (ch & UARTDR_FRMERR)
+				port->icount.frame++;
+			if (ch & UARTDR_OVERR)
+				port->icount.overrun++;
+
+			ch &= port->read_status_mask;
+
+			if (ch & UARTDR_PARERR)
+				flg = TTY_PARITY;
+			else if (ch & UARTDR_FRMERR)
+				flg = TTY_FRAME;
+
+#ifdef SUPPORT_SYSRQ
+			port->sysrq = 0;
+#endif
+		}
 
 		if (uart_handle_sysrq_char(port, ch, regs))
 			goto ignore_char;
 
-	error_return:
-		tty_insert_flip_char(tty, ch, flg);
-	ignore_char:
-		status = clps_readl(SYSFLG(port));
-	}
- out:
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-
- handle_error:
-	if (ch & UARTDR_PARERR)
-		port->icount.parity++;
-	else if (ch & UARTDR_FRMERR)
-		port->icount.frame++;
-	if (ch & UARTDR_OVERR)
-		port->icount.overrun++;
-
-	if (ch & port->ignore_status_mask) {
-		if (++ignored > 100)
-			goto out;
-		goto ignore_char;
-	}
-	ch &= port->read_status_mask;
-
-	if (ch & UARTDR_PARERR)
-		flg = TTY_PARITY;
-	else if (ch & UARTDR_FRMERR)
-		flg = TTY_FRAME;
-
-	if (ch & UARTDR_OVERR) {
 		/*
 		 * CHECK: does overrun affect the current character?
 		 * ASSUMPTION: it does not.
 		 */
-		tty_insert_flip_char(tty, ch, flg);
-		ch = 0;
-		flg = TTY_OVERRUN;
+		if ((ch & port->ignore_status_mask & ~RXSTAT_OVERRUN) == 0)
+			tty_insert_flip_char(tty, ch, flg);
+		if ((ch & ~port->ignore_status_mask & RXSTAT_OVERRUN) == 0)
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+	ignore_char:
+		status = clps_readl(SYSFLG(port));
 	}
-#ifdef SUPPORT_SYSRQ
-	port->sysrq = 0;
-#endif
-	goto error_return;
+	tty_flip_buffer_push(tty);
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index c682c63..01a8726 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -321,18 +321,39 @@
 #define TXTL 2 /* reset default */
 #define RXTL 1 /* reset default */
 
+static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
+{
+	unsigned int val;
+	unsigned int ufcr_rfdiv;
+
+	/* set receiver / transmitter trigger level.
+	 * RFDIV is set such way to satisfy requested uartclk value
+	 */
+	val = TXTL<<10 | RXTL;
+	ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk;
+
+	if(!ufcr_rfdiv)
+		ufcr_rfdiv = 1;
+
+	if(ufcr_rfdiv >= 7)
+		ufcr_rfdiv = 6;
+	else
+		ufcr_rfdiv = 6 - ufcr_rfdiv;
+
+	val |= UFCR_RFDIV & (ufcr_rfdiv << 7);
+
+	UFCR((u32)sport->port.membase) = val;
+
+	return 0;
+}
+
 static int imx_startup(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	int retval;
-	unsigned int val;
 	unsigned long flags;
 
-	/* set receiver / transmitter trigger level. We assume
-	 * that RFDIV has been set by the arch setup or by the bootloader.
-	 */
-	val = (UFCR((u32)sport->port.membase) & UFCR_RFDIV)  | TXTL<<10 | RXTL;
-	UFCR((u32)sport->port.membase) = val;
+	imx_setup_ufcr(sport, 0);
 
 	/* disable the DREN bit (Data Ready interrupt enable) before
 	 * requesting IRQs
@@ -737,9 +758,12 @@
 imx_console_get_options(struct imx_port *sport, int *baud,
 			   int *parity, int *bits)
 {
+
 	if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) {
 		/* ok, the port was enabled */
 		unsigned int ucr2, ubir,ubmr, uartclk;
+		unsigned int baud_raw;
+		unsigned int ucfr_rfdiv;
 
 		ucr2 = UCR2((u32)sport->port.membase);
 
@@ -758,9 +782,35 @@
 
 		ubir = UBIR((u32)sport->port.membase) & 0xffff;
 		ubmr = UBMR((u32)sport->port.membase) & 0xffff;
-		uartclk = sport->port.uartclk;
 
-		*baud = ((uartclk/16) * (ubir + 1)) / (ubmr + 1);
+
+		ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7;
+		if (ucfr_rfdiv == 6)
+			ucfr_rfdiv = 7;
+		else
+			ucfr_rfdiv = 6 - ucfr_rfdiv;
+
+		uartclk = imx_get_perclk1();
+		uartclk /= ucfr_rfdiv;
+
+		{	/*
+			 * The next code provides exact computation of
+			 *   baud_raw = round(((uartclk/16) * (ubir + 1)) / (ubmr + 1))
+			 * without need of float support or long long division,
+			 * which would be required to prevent 32bit arithmetic overflow
+			 */
+			unsigned int mul = ubir + 1;
+			unsigned int div = 16 * (ubmr + 1);
+			unsigned int rem = uartclk % div;
+
+			baud_raw = (uartclk / div) * mul;
+			baud_raw += (rem * mul + div / 2) / div;
+			*baud = (baud_raw + 50) / 100 * 100;
+		}
+
+		if(*baud != baud_raw)
+			printk(KERN_INFO "Serial: Console IMX rounded baud rate from %d to %d\n",
+				baud_raw, *baud);
 	}
 }
 
@@ -787,6 +837,8 @@
 	else
 		imx_console_get_options(sport, &baud, &parity, &bits);
 
+	imx_setup_ufcr(sport, 0);
+
 	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }
 
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index d054f12..ba4e13a 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -838,7 +838,7 @@
 	port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
 	writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
 	port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
-	writel(port->ip_rx_cons, &port->ip_serial_regs->srcir);
+	writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir);
 
 	/* Disable interrupts for this 16550 */
 	uart = port->ip_uart_regs;
@@ -1272,8 +1272,9 @@
 	 * and set the rx threshold to that amount.  There are 4 chars
 	 * per ring entry, so we'll divide the number of chars that will
 	 * arrive in timeout by 4.
+	 * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
 	 */
-	threshold = timeout * port->ip_baud / 10 / HZ / 4;
+	threshold = timeout * port->ip_baud / 4000;
 	if (threshold == 0)
 		threshold = 1;	/* otherwise we'll intr all the time! */
 
@@ -1285,8 +1286,10 @@
 
 	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
 
-	/* Now set the rx timeout to the given value */
-	timeout = timeout * IOC4_SRTR_HZ / HZ;
+	/* Now set the rx timeout to the given value
+	 * again timeout * IOC4_SRTR_HZ / HZ
+	 */
+	timeout = timeout * IOC4_SRTR_HZ / 100;
 	if (timeout > IOC4_SRTR_CNT)
 		timeout = IOC4_SRTR_CNT;
 
@@ -1380,7 +1383,7 @@
 	if (port->ip_tx_lowat == 0)
 		port->ip_tx_lowat = 1;
 
-	set_rx_timeout(port, port->ip_rx_timeout);
+	set_rx_timeout(port, 2);
 
 	return 0;
 }
@@ -1685,8 +1688,8 @@
 {
 	struct ioc4_port *port = get_ioc4_port(the_port);
 	int baud, bits;
-	unsigned cflag, cval;
-	int new_parity = 0, new_parity_enable = 0, new_stop = 1, new_data = 8;
+	unsigned cflag;
+	int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
 	struct uart_info *info = the_port->info;
 
 	cflag = new_termios->c_cflag;
@@ -1694,48 +1697,35 @@
 	switch (cflag & CSIZE) {
 	case CS5:
 		new_data = 5;
-		cval = 0x00;
 		bits = 7;
 		break;
 	case CS6:
 		new_data = 6;
-		cval = 0x01;
 		bits = 8;
 		break;
 	case CS7:
 		new_data = 7;
-		cval = 0x02;
 		bits = 9;
 		break;
 	case CS8:
 		new_data = 8;
-		cval = 0x03;
 		bits = 10;
 		break;
 	default:
 		/* cuz we always need a default ... */
 		new_data = 5;
-		cval = 0x00;
 		bits = 7;
 		break;
 	}
 	if (cflag & CSTOPB) {
-		cval |= 0x04;
 		bits++;
 		new_stop = 1;
 	}
 	if (cflag & PARENB) {
-		cval |= UART_LCR_PARITY;
 		bits++;
 		new_parity_enable = 1;
-	}
-	if (cflag & PARODD) {
-		cval |= UART_LCR_EPAR;
-		new_parity = 1;
-	}
-	if (cflag & IGNPAR) {
-		cval &= ~UART_LCR_PARITY;
-		new_parity_enable = 0;
+		if (cflag & PARODD)
+			new_parity = 1;
 	}
 	baud = uart_get_baud_rate(the_port, new_termios, old_termios,
 				MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
@@ -1765,10 +1755,15 @@
 		the_port->ignore_status_mask &= ~N_DATA_READY;
 	}
 
-	if (cflag & CRTSCTS)
+	if (cflag & CRTSCTS) {
 		info->flags |= ASYNC_CTS_FLOW;
-	else
+		port->ip_sscr |= IOC4_SSCR_HFC_EN;
+	}
+	else {
 		info->flags &= ~ASYNC_CTS_FLOW;
+		port->ip_sscr &= ~IOC4_SSCR_HFC_EN;
+	}
+	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
 
 	/* Set the configuration and proper notification call */
 	DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
@@ -1825,12 +1820,6 @@
 	/* set the speed of the serial port */
 	ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
 
-	/* enable hardware flow control - after ioc4_change_speed because
-	 * ASYNC_CTS_FLOW is set there */
-	if (info->flags & ASYNC_CTS_FLOW) {
-		port->ip_sscr |= IOC4_SSCR_HFC_EN;
-		writel(port->ip_sscr, &port->ip_serial_regs->sscr);
-	}
 	info->flags |= UIF_INITIALIZED;
 	return 0;
 }
@@ -1847,7 +1836,6 @@
 	}
 }
 
-
 /**
  * handle_intr - service any interrupts for the given port - 2nd level
  *			called via sd_intr
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index e071761..777829f 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -393,7 +393,6 @@
 int jsm_uart_port_init(struct jsm_board *);
 int jsm_remove_uart_port(struct jsm_board *);
 void jsm_input(struct jsm_channel *ch);
-void jsm_carrier(struct jsm_channel *ch);
 void jsm_check_queue_flow_control(struct jsm_channel *ch);
 
 #endif
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 9b79c1f..3a11a69 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -688,7 +688,7 @@
 /*
  * No locks are assumed to be held when calling this function.
  */
-void neo_clear_break(struct jsm_channel *ch, int force)
+static void neo_clear_break(struct jsm_channel *ch, int force)
 {
 	unsigned long lock_flags;
 
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 24fe76c..98de225 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -31,6 +31,8 @@
 
 #include "jsm.h"
 
+static void jsm_carrier(struct jsm_channel *ch);
+
 static inline int jsm_get_mstat(struct jsm_channel *ch)
 {
 	unsigned char mstat;
@@ -755,7 +757,7 @@
 	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
 }
 
-void jsm_carrier(struct jsm_channel *ch)
+static void jsm_carrier(struct jsm_channel *ch)
 {
 	struct jsm_board *bd;
 
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index d0dfc3c..a8314ae 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -329,8 +329,8 @@
 	mpsc_sdma_cmd(pi, SDMA_SDCM_AR | SDMA_SDCM_AT);
 
 	/* Clear the SDMA current and first TX and RX pointers */
-	mpsc_sdma_set_tx_ring(pi, 0);
-	mpsc_sdma_set_rx_ring(pi, 0);
+	mpsc_sdma_set_tx_ring(pi, NULL);
+	mpsc_sdma_set_rx_ring(pi, NULL);
 
 	/* Disable interrupts */
 	mpsc_sdma_intr_mask(pi, 0xf);
@@ -1540,8 +1540,8 @@
 			MPSC_SDMA_INTR_REG_BLOCK_SIZE);
 	}
 
-	mpsc_shared_regs.mpsc_routing_base = 0;
-	mpsc_shared_regs.sdma_intr_base = 0;
+	mpsc_shared_regs.mpsc_routing_base = NULL;
+	mpsc_shared_regs.sdma_intr_base = NULL;
 
 	mpsc_shared_regs.mpsc_routing_base_p = 0;
 	mpsc_shared_regs.sdma_intr_base_p = 0;
@@ -1678,9 +1678,9 @@
 		release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE);
 	}
 
-	pi->mpsc_base = 0;
-	pi->sdma_base = 0;
-	pi->brg_base = 0;
+	pi->mpsc_base = NULL;
+	pi->sdma_base = NULL;
+	pi->brg_base = NULL;
 
 	pi->mpsc_base_p = 0;
 	pi->sdma_base_p = 0;
diff --git a/drivers/serial/mpsc.h b/drivers/serial/mpsc.h
index 1f7294b..678dbcf 100644
--- a/drivers/serial/mpsc.h
+++ b/drivers/serial/mpsc.h
@@ -83,8 +83,8 @@
 	phys_addr_t mpsc_routing_base_p;
 	phys_addr_t sdma_intr_base_p;
 
-	void *mpsc_routing_base;
-	void *sdma_intr_base;
+	void __iomem *mpsc_routing_base;
+	void __iomem *sdma_intr_base;
 
 	u32 MPSC_MRR_m;
 	u32 MPSC_RCRR_m;
@@ -120,9 +120,9 @@
 	phys_addr_t brg_base_p;
 
 	/* Virtual addresses of various blocks of registers (from platform) */
-	void *mpsc_base;
-	void *sdma_base;
-	void *brg_base;
+	void __iomem *mpsc_base;
+	void __iomem *sdma_base;
+	void __iomem *brg_base;
 
 	/* Descriptor ring and buffer allocations */
 	void *dma_region;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index bd6782a..435750d 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -364,7 +364,7 @@
 		flag = TTY_NORMAL;
 		port->icount.rx++;
 
-		if (uerstat & S3C2410_UERSTAT_ANY) {
+		if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
 			dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
 			    ch, uerstat);
 
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 0860652..157218b 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -214,56 +214,39 @@
 		 * note that the error handling code is
 		 * out of the main execution path
 		 */
-		if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
-			goto handle_error;
+		if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) {
+			if (status & UTSR1_TO_SM(UTSR1_PRE))
+				sport->port.icount.parity++;
+			else if (status & UTSR1_TO_SM(UTSR1_FRE))
+				sport->port.icount.frame++;
+			if (status & UTSR1_TO_SM(UTSR1_ROR))
+				sport->port.icount.overrun++;
+
+			status &= sport->port.read_status_mask;
+
+			if (status & UTSR1_TO_SM(UTSR1_PRE))
+				flg = TTY_PARITY;
+			else if (status & UTSR1_TO_SM(UTSR1_FRE))
+				flg = TTY_FRAME;
+
+#ifdef SUPPORT_SYSRQ
+			sport->port.sysrq = 0;
+#endif
+		}
 
 		if (uart_handle_sysrq_char(&sport->port, ch, regs))
 			goto ignore_char;
 
-	error_return:
-		tty_insert_flip_char(tty, ch, flg);
+		if ((status & port->ignore_status_mask & ~UTSR1_TO_SM(UTSR1_ROR)) == 0)
+			tty_insert_flip_char(tty, ch, flg);
+		if (status & ~port->ignore_status_mask & UTSR1_TO_SM(UTSR1_ROR))
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
 	ignore_char:
 		status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
 			 UTSR0_TO_SM(UART_GET_UTSR0(sport));
 	}
- out:
 	tty_flip_buffer_push(tty);
-	return;
-
- handle_error:
-	if (status & UTSR1_TO_SM(UTSR1_PRE))
-		sport->port.icount.parity++;
-	else if (status & UTSR1_TO_SM(UTSR1_FRE))
-		sport->port.icount.frame++;
-	if (status & UTSR1_TO_SM(UTSR1_ROR))
-		sport->port.icount.overrun++;
-
-	if (status & sport->port.ignore_status_mask) {
-		if (++ignored > 100)
-			goto out;
-		goto ignore_char;
-	}
-
-	status &= sport->port.read_status_mask;
-
-	if (status & UTSR1_TO_SM(UTSR1_PRE))
-		flg = TTY_PARITY;
-	else if (status & UTSR1_TO_SM(UTSR1_FRE))
-		flg = TTY_FRAME;
-
-	if (status & UTSR1_TO_SM(UTSR1_ROR)) {
-		/*
-		 * overrun does *not* affect the character
-		 * we read from the FIFO
-		 */
-		tty_insert_flip_char(tty, ch, flg);
-		ch = 0;
-		flg = TTY_OVERRUN;
-	}
-#ifdef SUPPORT_SYSRQ
-	sport->port.sysrq = 0;
-#endif
-	goto error_return;
 }
 
 static void sa1100_tx_chars(struct sa1100_port *sport)
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 9034f9a..6eeb48f 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -107,6 +107,13 @@
 	int			line[4];
 };
 
+struct serial_cfg_mem {
+	tuple_t tuple;
+	cisparse_t parse;
+	u_char buf[256];
+};
+
+
 static void serial_config(dev_link_t * link);
 static int serial_event(event_t event, int priority,
 			event_callback_args_t * args);
@@ -357,14 +364,24 @@
 	static int size_table[2] = { 8, 16 };
 	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
-	tuple_t tuple;
-	u_char buf[256];
-	cisparse_t parse;
-	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+	struct serial_cfg_mem *cfg_mem;
+	tuple_t *tuple;
+	u_char *buf;
+	cisparse_t *parse;
+	cistpl_cftable_entry_t *cf;
 	config_info_t config;
 	int i, j, try;
 	int s;
 
+	cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
+	if (!cfg_mem)
+		return -1;
+
+	tuple = &cfg_mem->tuple;
+	parse = &cfg_mem->parse;
+	cf = &parse->cftable_entry;
+	buf = cfg_mem->buf;
+
 	/* If the card is already configured, look up the port and irq */
 	i = pcmcia_get_configuration_info(handle, &config);
 	if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
@@ -377,21 +394,23 @@
 			port = config.BasePort1 + 0x28;
 			info->slave = 1;
 		}
-		if (info->slave)
+		if (info->slave) {
+			kfree(cfg_mem);
 			return setup_serial(handle, info, port, config.AssignedIRQ);
+		}
 	}
 	link->conf.Vcc = config.Vcc;
 
 	/* First pass: look for a config entry that looks normal. */
-	tuple.TupleData = (cisdata_t *) buf;
-	tuple.TupleOffset = 0;
-	tuple.TupleDataMax = 255;
-	tuple.Attributes = 0;
-	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	tuple->TupleData = (cisdata_t *) buf;
+	tuple->TupleOffset = 0;
+	tuple->TupleDataMax = 255;
+	tuple->Attributes = 0;
+	tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	/* Two tries: without IO aliases, then with aliases */
 	for (s = 0; s < 2; s++) {
 		for (try = 0; try < 2; try++) {
-			i = first_tuple(handle, &tuple, &parse);
+			i = first_tuple(handle, tuple, parse);
 			while (i != CS_NO_MORE_ITEMS) {
 				if (i != CS_SUCCESS)
 					goto next_entry;
@@ -409,14 +428,14 @@
 						goto found_port;
 				}
 next_entry:
-				i = next_tuple(handle, &tuple, &parse);
+				i = next_tuple(handle, tuple, parse);
 			}
 		}
 	}
 	/* Second pass: try to find an entry that isn't picky about
 	   its base address, then try to grab any standard serial port
 	   address, and finally try to get any free port. */
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(handle, tuple, parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
 		    ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -429,7 +448,7 @@
 					goto found_port;
 			}
 		}
-		i = next_tuple(handle, &tuple, &parse);
+		i = next_tuple(handle, tuple, parse);
 	}
 
       found_port:
@@ -437,6 +456,7 @@
 		printk(KERN_NOTICE
 		       "serial_cs: no usable port range found, giving up\n");
 		cs_error(link->handle, RequestIO, i);
+		kfree(cfg_mem);
 		return -1;
 	}
 
@@ -450,9 +470,10 @@
 	i = pcmcia_request_configuration(link->handle, &link->conf);
 	if (i != CS_SUCCESS) {
 		cs_error(link->handle, RequestConfiguration, i);
+		kfree(cfg_mem);
 		return -1;
 	}
-
+	kfree(cfg_mem);
 	return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
 }
 
@@ -460,29 +481,39 @@
 {
 	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
-	tuple_t tuple;
-	u_char buf[256];
-	cisparse_t parse;
-	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+	struct serial_cfg_mem *cfg_mem;
+	tuple_t *tuple;
+	u_char *buf;
+	cisparse_t *parse;
+	cistpl_cftable_entry_t *cf;
 	config_info_t config;
-	int i, base2 = 0;
+	int i, rc, base2 = 0;
+
+	cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
+	if (!cfg_mem)
+		return -1;
+	tuple = &cfg_mem->tuple;
+	parse = &cfg_mem->parse;
+	cf = &parse->cftable_entry;
+	buf = cfg_mem->buf;
 
 	i = pcmcia_get_configuration_info(handle, &config);
 	if (i != CS_SUCCESS) {
 		cs_error(handle, GetConfigurationInfo, i);
-		return -1;
+		rc = -1;
+		goto free_cfg_mem;
 	}
 	link->conf.Vcc = config.Vcc;
 
-	tuple.TupleData = (cisdata_t *) buf;
-	tuple.TupleOffset = 0;
-	tuple.TupleDataMax = 255;
-	tuple.Attributes = 0;
-	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	tuple->TupleData = (cisdata_t *) buf;
+	tuple->TupleOffset = 0;
+	tuple->TupleDataMax = 255;
+	tuple->Attributes = 0;
+	tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
 	/* First, look for a generic full-sized window */
 	link->io.NumPorts1 = info->multi * 8;
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(handle, tuple, parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		/* The quad port cards have bad CIS's, so just look for a
 		   window larger than 8 ports and assume it will be right */
@@ -497,14 +528,14 @@
 			if (i == CS_SUCCESS)
 				break;
 		}
-		i = next_tuple(handle, &tuple, &parse);
+		i = next_tuple(handle, tuple, parse);
 	}
 
 	/* If that didn't work, look for two windows */
 	if (i != CS_SUCCESS) {
 		link->io.NumPorts1 = link->io.NumPorts2 = 8;
 		info->multi = 2;
-		i = first_tuple(handle, &tuple, &parse);
+		i = first_tuple(handle, tuple, parse);
 		while (i != CS_NO_MORE_ITEMS) {
 			if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
 				link->conf.ConfigIndex = cf->index;
@@ -517,13 +548,14 @@
 				if (i == CS_SUCCESS)
 					break;
 			}
-			i = next_tuple(handle, &tuple, &parse);
+			i = next_tuple(handle, tuple, parse);
 		}
 	}
 
 	if (i != CS_SUCCESS) {
 		cs_error(link->handle, RequestIO, i);
-		return -1;
+		rc = -1;
+		goto free_cfg_mem;
 	}
 
 	i = pcmcia_request_irq(link->handle, &link->irq);
@@ -541,7 +573,8 @@
 	i = pcmcia_request_configuration(link->handle, &link->conf);
 	if (i != CS_SUCCESS) {
 		cs_error(link->handle, RequestConfiguration, i);
-		return -1;
+		rc = -1;
+		goto free_cfg_mem;
 	}
 
 	/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
@@ -554,17 +587,23 @@
 			setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
 			outb(12, base2 + 1);
 		}
-		return 0;
+		rc = 0;
+		goto free_cfg_mem;
 	}
 
 	setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
 	/* The Nokia cards are not really multiport cards */
-	if (info->manfid == MANFID_NOKIA)
-		return 0;
+	if (info->manfid == MANFID_NOKIA) {
+		rc = 0;
+		goto free_cfg_mem;
+	}
 	for (i = 0; i < info->multi - 1; i++)
-		setup_serial(handle, info, base2 + (8 * i), link->irq.AssignedIRQ);
-
-	return 0;
+		setup_serial(handle, info, base2 + (8 * i),
+				link->irq.AssignedIRQ);
+	rc = 0;
+free_cfg_mem:
+	kfree(cfg_mem);
+	return rc;
 }
 
 /*======================================================================
@@ -579,39 +618,49 @@
 {
 	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
-	tuple_t tuple;
-	u_short buf[128];
-	cisparse_t parse;
-	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+	struct serial_cfg_mem *cfg_mem;
+	tuple_t *tuple;
+	u_char *buf;
+	cisparse_t *parse;
+	cistpl_cftable_entry_t *cf;
 	int i, last_ret, last_fn;
 
 	DEBUG(0, "serial_config(0x%p)\n", link);
 
-	tuple.TupleData = (cisdata_t *) buf;
-	tuple.TupleOffset = 0;
-	tuple.TupleDataMax = 255;
-	tuple.Attributes = 0;
+	cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
+	if (!cfg_mem)
+		goto failed;
+
+	tuple = &cfg_mem->tuple;
+	parse = &cfg_mem->parse;
+	cf = &parse->cftable_entry;
+	buf = cfg_mem->buf;
+
+	tuple->TupleData = (cisdata_t *) buf;
+	tuple->TupleOffset = 0;
+	tuple->TupleDataMax = 255;
+	tuple->Attributes = 0;
 	/* Get configuration register information */
-	tuple.DesiredTuple = CISTPL_CONFIG;
-	last_ret = first_tuple(handle, &tuple, &parse);
+	tuple->DesiredTuple = CISTPL_CONFIG;
+	last_ret = first_tuple(handle, tuple, parse);
 	if (last_ret != CS_SUCCESS) {
 		last_fn = ParseTuple;
 		goto cs_failed;
 	}
-	link->conf.ConfigBase = parse.config.base;
-	link->conf.Present = parse.config.rmask[0];
+	link->conf.ConfigBase = parse->config.base;
+	link->conf.Present = parse->config.rmask[0];
 
 	/* Configure card */
 	link->state |= DEV_CONFIG;
 
 	/* Is this a compliant multifunction card? */
-	tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
-	tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
-	info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS);
+	tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
+	tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
+	info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS);
 
 	/* Is this a multiport card? */
-	tuple.DesiredTuple = CISTPL_MANFID;
-	if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+	tuple->DesiredTuple = CISTPL_MANFID;
+	if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
 		info->manfid = le16_to_cpu(buf[0]);
 		for (i = 0; i < MULTI_COUNT; i++)
 			if ((info->manfid == multi_id[i].manfid) &&
@@ -623,13 +672,13 @@
 
 	/* Another check for dual-serial cards: look for either serial or
 	   multifunction cards that ask for appropriate IO port ranges */
-	tuple.DesiredTuple = CISTPL_FUNCID;
+	tuple->DesiredTuple = CISTPL_FUNCID;
 	if ((info->multi == 0) &&
-	    ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) ||
-	     (parse.funcid.func == CISTPL_FUNCID_MULTI) ||
-	     (parse.funcid.func == CISTPL_FUNCID_SERIAL))) {
-		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-		if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+	    ((first_tuple(handle, tuple, parse) != CS_SUCCESS) ||
+	     (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
+	     (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
+		tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+		if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
 			if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
 				info->multi = cf->io.win[0].len >> 3;
 			if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
@@ -664,6 +713,7 @@
 
 	link->dev = &info->node[0];
 	link->state &= ~DEV_CONFIG_PENDING;
+	kfree(cfg_mem);
 	return;
 
  cs_failed:
@@ -671,6 +721,7 @@
  failed:
 	serial_remove(link);
 	link->state &= ~DEV_CONFIG_PENDING;
+	kfree(cfg_mem);
 }
 
 /*======================================================================
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 4ce3a41..85cfa08 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -162,7 +162,7 @@
 		flag = TTY_NORMAL;
 		++port->icount.rx;
 
-		if (data & RxError) {	/* Quick check, short-circuit */
+		if (unlikely(data & RxError)) {	/* Quick check, short-circuit */
 			if (data & RxBreak) {
 				data &= ~(RxFramingError | RxParityError);
 				++port->icount.brk;
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index ffaab9b..fee6418 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -787,7 +787,7 @@
 
 static void sn_sal_console_write(struct console *, const char *, unsigned);
 static int __init sn_sal_console_setup(struct console *, char *);
-extern struct uart_driver sal_console_uart;
+static struct uart_driver sal_console_uart;
 extern struct tty_driver *uart_console_device(struct console *, int *);
 
 static struct console sal_console = {
@@ -801,7 +801,7 @@
 
 #define SAL_CONSOLE	&sal_console
 
-struct uart_driver sal_console_uart = {
+static struct uart_driver sal_console_uart = {
 	.owner = THIS_MODULE,
 	.driver_name = "sn_console",
 	.dev_name = DEVICE_NAME,
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 8caaf2e..39b788d 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -682,7 +682,8 @@
 
 /* Internal routine, port->lock is held and local interrupts are disabled.  */
 static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cflag,
-				  unsigned int iflag, int baud)
+				  unsigned int iflag, unsigned int baud,
+				  unsigned int quot)
 {
 	unsigned int ebrg;
 	unsigned char dafo;
@@ -766,6 +767,9 @@
 		up->port.ignore_status_mask |= (SAB82532_ISR0_RPF |
 						SAB82532_ISR0_TCD);
 
+	uart_update_timeout(&up->port, cflag,
+			    (up->port.uartclk / (16 * quot)));
+
 	/* Now bang the new settings into the chip.  */
 	sunsab_cec_wait(up);
 	sunsab_tec_wait(up);
@@ -784,10 +788,11 @@
 {
 	struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
 	unsigned long flags;
-	int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
+	unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
+	unsigned int quot = uart_get_divisor(port, baud);
 
 	spin_lock_irqsave(&up->port.lock, flags);
-	sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud);
+	sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud, quot);
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
@@ -880,7 +885,7 @@
 {
 	struct uart_sunsab_port *up = &sunsab_ports[con->index];
 	unsigned long flags;
-	int baud;
+	unsigned int baud, quot;
 
 	printk("Console: ttyS%d (SAB82532)\n",
 	       (sunsab_reg.minor - 64) + con->index);
@@ -926,7 +931,8 @@
 				SAB82532_IMR1_XPR;
 	writeb(up->interrupt_mask1, &up->regs->w.imr1);
 
-	sunsab_convert_to_sab(up, con->cflag, 0, baud);
+	quot = uart_get_divisor(&up->port, baud);
+	sunsab_convert_to_sab(up, con->cflag, 0, baud, quot);
 	sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 23d19d3..ddc97c9 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1285,6 +1285,7 @@
 
 static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
 {
+	int quot, baud;
 #ifdef CONFIG_SERIO
 	struct serio *serio;
 #endif
@@ -1293,10 +1294,14 @@
 	up->port.type = PORT_UNKNOWN;
 	up->port.uartclk = (SU_BASE_BAUD * 16);
 
-	if (up->su_type == SU_PORT_KBD)
+	if (up->su_type == SU_PORT_KBD) {
 		up->cflag = B1200 | CS8 | CLOCAL | CREAD;
-	else
+		baud = 1200;
+	} else {
 		up->cflag = B4800 | CS8 | CLOCAL | CREAD;
+		baud = 4800;
+	}
+	quot = up->port.uartclk / (16 * baud);
 
 	sunsu_autoconfig(up);
 	if (up->port.type == PORT_UNKNOWN)
@@ -1337,6 +1342,8 @@
 	}
 #endif
 
+	sunsu_change_speed(&up->port, up->cflag, 0, quot);
+
 	sunsu_startup(&up->port);
 	return 0;
 }
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 5538756..d5863b8 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -41,9 +41,6 @@
  *
  ***************************************************************************/
 
-static char ixj_c_rcsid[] = "$Id: ixj.c,v 4.7 2001/08/13 06:19:33 craigs Exp $";
-static char ixj_c_revision[] = "$Revision: 4.7 $";
-
 /*
  * $Log: ixj.c,v $
  *
@@ -6172,8 +6169,14 @@
 		retval = j->serial;
 		break;
 	case IXJCTL_VERSION:
-		if (copy_to_user(argp, ixj_c_revision, strlen(ixj_c_revision))) 
-			retval = -EFAULT;
+		{
+			char arg_str[100];
+			snprintf(arg_str, sizeof(arg_str),
+				"\nDriver version %i.%i.%i", IXJ_VER_MAJOR,
+				IXJ_VER_MINOR, IXJ_BLD_VER);
+			if (copy_to_user(argp, arg_str, strlen(arg_str)))
+				retval = -EFAULT;
+		}
 		break;
 	case PHONE_RING_CADENCE:
 		j->ring_cadence = arg;
@@ -7168,9 +7171,6 @@
 	int cnt;
 	IXJ *j;
 	len = 0;
-	len += sprintf(buf + len, "%s", ixj_c_rcsid);
-	len += sprintf(buf + len, "\n%s", ixj_h_rcsid);
-	len += sprintf(buf + len, "\n%s", ixjuser_h_rcsid);
 	len += sprintf(buf + len, "\nDriver version %i.%i.%i", IXJ_VER_MAJOR, IXJ_VER_MINOR, IXJ_BLD_VER);
 	len += sprintf(buf + len, "\nsizeof IXJ struct %Zd bytes", sizeof(IXJ));
 	len += sprintf(buf + len, "\nsizeof DAA struct %Zd bytes", sizeof(DAA_REGS));
@@ -7790,7 +7790,7 @@
 	if ((probe = ixj_probe_pci(&cnt)) < 0) {
 		return probe;
 	}
-	printk("%s\n", ixj_c_rcsid);
+	printk(KERN_INFO "ixj driver initialized.\n");
 	create_proc_read_entry ("ixj", 0, NULL, ixj_read_proc, NULL);
 	return probe;
 }
diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
index 143818a..51e3f7f 100644
--- a/drivers/telephony/ixj.h
+++ b/drivers/telephony/ixj.h
@@ -38,8 +38,6 @@
  * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  *****************************************************************************/
-static char ixj_h_rcsid[] = "$Id: ixj.h,v 4.1 2001/08/04 14:49:27 craigs Exp $";
-
 #define IXJ_VERSION 3031
 
 #include <linux/version.h>
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e12c5be..f50aaf2 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -431,7 +431,7 @@
  * (2) error, where io->status is a negative errno value.  The number
  *     of io->bytes transferred before the error is usually less
  *     than requested, and can be nonzero.
- * (3) cancelation, a type of error with status -ECONNRESET that
+ * (3) cancellation, a type of error with status -ECONNRESET that
  *     is initiated by usb_sg_cancel().
  *
  * When this function returns, all memory allocated through usb_sg_init() or
@@ -1282,7 +1282,7 @@
  * bus rwsem; usb device driver probe() methods cannot use this routine.
  *
  * Returns zero on success, or else the status code returned by the
- * underlying call that failed.  On succesful completion, each interface
+ * underlying call that failed.  On successful completion, each interface
  * in the original device configuration has been destroyed, and each one
  * in the new configuration has been probed by all relevant usb device
  * drivers currently known to the kernel.
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 1697215..0faf18d 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -121,7 +121,7 @@
  * describing that request to the USB subsystem.  Request completion will
  * be indicated later, asynchronously, by calling the completion handler.
  * The three types of completion are success, error, and unlink
- * (a software-induced fault, also called "request cancelation").  
+ * (a software-induced fault, also called "request cancellation").  
  *
  * URBs may be submitted in interrupt context.
  *
@@ -170,7 +170,7 @@
  * As of Linux 2.6, all USB endpoint transfer queues support depths greater
  * than one.  This was previously a HCD-specific behavior, except for ISO
  * transfers.  Non-isochronous endpoint queues are inactive during cleanup
- * after faults (transfer errors or cancelation).
+ * after faults (transfer errors or cancellation).
  *
  * Reserved Bandwidth Transfers:
  *
@@ -395,7 +395,7 @@
  *
  * This routine cancels an in-progress request.  URBs complete only
  * once per submission, and may be canceled only once per submission.
- * Successful cancelation means the requests's completion handler will
+ * Successful cancellation means the requests's completion handler will
  * be called with a status code indicating that the request has been
  * canceled (rather than any other code) and will quickly be removed
  * from host controller data structures.
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index c231b4b..25cf7e9 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -611,11 +611,10 @@
 
 		if (add_hotplug_env_var(envp, num_envp, &i,
 					buffer, buffer_size, &length,
-					"MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+					"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
 					le16_to_cpu(usb_dev->descriptor.idVendor),
 					le16_to_cpu(usb_dev->descriptor.idProduct),
 					le16_to_cpu(usb_dev->descriptor.bcdDevice),
-					le16_to_cpu(usb_dev->descriptor.bcdDevice),
 					usb_dev->descriptor.bDeviceClass,
 					usb_dev->descriptor.bDeviceSubClass,
 					usb_dev->descriptor.bDeviceProtocol,
@@ -626,11 +625,10 @@
  	} else {
 		if (add_hotplug_env_var(envp, num_envp, &i,
 					buffer, buffer_size, &length,
-					"MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
+					"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
 					le16_to_cpu(usb_dev->descriptor.idVendor),
 					le16_to_cpu(usb_dev->descriptor.idProduct),
 					le16_to_cpu(usb_dev->descriptor.bcdDevice),
-					le16_to_cpu(usb_dev->descriptor.bcdDevice),
 					usb_dev->descriptor.bDeviceClass,
 					usb_dev->descriptor.bDeviceSubClass,
 					usb_dev->descriptor.bDeviceProtocol))
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 3993156..3f783cb 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -569,7 +569,7 @@
 
 /* include the status endpoint if we can, even where it's optional.
  * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
- * packet, to simplify cancelation; and a big transfer interval, to
+ * packet, to simplify cancellation; and a big transfer interval, to
  * waste less bandwidth.
  *
  * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 2cff67c..1e5e6dd 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -275,7 +275,7 @@
  *
  * After opening, configure non-control endpoints.  Then use normal
  * stream read() and write() requests; and maybe ioctl() to get more
- * precise FIFO status when recovering from cancelation.
+ * precise FIFO status when recovering from cancellation.
  */
 
 static void epio_complete (struct usb_ep *ep, struct usb_request *req)
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 0def9f7..df75ab6 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -705,7 +705,7 @@
 		done(ep, req, status);
 	}
 
-	/* Disable IRQ if EP is enabled (has decriptor) */
+	/* Disable IRQ if EP is enabled (has descriptor) */
 	if (ep->desc)
 		pio_irq_disable(ep_index(ep));
 }
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f1762ed..4d591c7 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -240,7 +240,7 @@
 	struct usb_ep		*dev_notify_ep;	/* address of notify endpoint */
 	struct usb_ep		*dev_in_ep;	/* address of in endpoint */
 	struct usb_ep		*dev_out_ep;	/* address of out endpoint */
-	struct usb_endpoint_descriptor		/* desciptor of notify ep */
+	struct usb_endpoint_descriptor		/* descriptor of notify ep */
 				*dev_notify_ep_desc;
 	struct usb_endpoint_descriptor		/* descriptor of in endpoint */
 				*dev_in_ep_desc;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 84d2b93..bc69bd7 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -346,6 +346,22 @@
 	return 0;
 }
 
+static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+{
+	unsigned port;
+
+	if (!HCS_PPC (ehci->hcs_params))
+		return;
+
+	ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
+	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
+		(void) ehci_hub_control(ehci_to_hcd(ehci),
+				is_on ? SetPortFeature : ClearPortFeature,
+				USB_PORT_FEAT_POWER,
+				port--, NULL, 0);
+	msleep(20);
+}
+
 
 /* called by khubd or root hub init threads */
 
@@ -362,8 +378,10 @@
 	dbg_hcs_params (ehci, "reset");
 	dbg_hcc_params (ehci, "reset");
 
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl (&ehci->caps->hcs_params);
+
 #ifdef	CONFIG_PCI
-	/* EHCI 0.96 and later may have "extended capabilities" */
 	if (hcd->self.controller->bus == &pci_bus_type) {
 		struct pci_dev	*pdev = to_pci_dev(hcd->self.controller);
 
@@ -383,9 +401,30 @@
 			break;
 		}
 
+		/* optional debug port, normally in the first BAR */
+		temp = pci_find_capability (pdev, 0x0a);
+		if (temp) {
+			pci_read_config_dword(pdev, temp, &temp);
+			temp >>= 16;
+			if ((temp & (3 << 13)) == (1 << 13)) {
+				temp &= 0x1fff;
+				ehci->debug = hcd->regs + temp;
+				temp = readl (&ehci->debug->control);
+				ehci_info (ehci, "debug port %d%s\n",
+					HCS_DEBUG_PORT(ehci->hcs_params),
+					(temp & DBGP_ENABLED)
+						? " IN USE"
+						: "");
+				if (!(temp & DBGP_ENABLED))
+					ehci->debug = NULL;
+			}
+		}
+
 		temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
 	} else
 		temp = 0;
+
+	/* EHCI 0.96 and later may have "extended capabilities" */
 	while (temp && count--) {
 		u32		cap;
 
@@ -414,8 +453,7 @@
 		ehci_reset (ehci);
 #endif
 
-	/* cache this readonly data; minimize PCI reads */
-	ehci->hcs_params = readl (&ehci->caps->hcs_params);
+	ehci_port_power (ehci, 0);
 
 	/* at least the Genesys GL880S needs fixup here */
 	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
@@ -657,16 +695,11 @@
 static void ehci_stop (struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	u8			rh_ports, port;
 
 	ehci_dbg (ehci, "stop\n");
 
 	/* Turn off port power on all root hub ports. */
-	rh_ports = HCS_N_PORTS (ehci->hcs_params);
-	for (port = 1; port <= rh_ports; port++)
-		(void) ehci_hub_control(hcd,
-			ClearPortFeature, USB_PORT_FEAT_POWER,
-			port, NULL, 0);
+	ehci_port_power (ehci, 0);
 
 	/* no more interrupts ... */
 	del_timer_sync (&ehci->watchdog);
@@ -748,7 +781,6 @@
 	unsigned		port;
 	struct usb_device	*root = hcd->self.root_hub;
 	int			retval = -EINVAL;
-	int			powerup = 0;
 
 	// maybe restore (PCI) FLADJ
 
@@ -766,8 +798,6 @@
 			up (&hcd->self.root_hub->serialize);
 			break;
 		}
-		if ((status & PORT_POWER) == 0)
-			powerup = 1;
 		if (!root->children [port])
 			continue;
 		dbg_port (ehci, __FUNCTION__, port + 1, status);
@@ -794,16 +824,9 @@
 		retval = ehci_start (hcd);
 
 		/* here we "know" root ports should always stay powered;
-		 * but some controllers may lost all power.
+		 * but some controllers may lose all power.
 		 */
-		if (powerup) {
-			ehci_dbg (ehci, "...powerup ports...\n");
-			for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
-				(void) ehci_hub_control(hcd,
-					SetPortFeature, USB_PORT_FEAT_POWER,
-						port--, NULL, 0);
-			msleep(20);
-		}
+		ehci_port_power (ehci, 1);
 	}
 
 	return retval;
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 2373537..02fefab 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -281,6 +281,8 @@
 	temp = 0x0008;			/* per-port overcurrent reporting */
 	if (HCS_PPC (ehci->hcs_params))
 		temp |= 0x0001;		/* per-port power control */
+	else
+		temp |= 0x0002;		/* no power switching */
 #if 0
 // re-enable when we support USB_PORT_FEAT_INDICATOR below.
 	if (HCS_INDICATOR (ehci->hcs_params))
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index e763a83..4df4982 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -47,6 +47,12 @@
 #define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
 
 struct ehci_hcd {			/* one per controller */
+	/* glue to PCI and HCD framework */
+	struct ehci_caps __iomem *caps;
+	struct ehci_regs __iomem *regs;
+	struct ehci_dbg_port __iomem *debug;
+
+	__u32			hcs_params;	/* cached register copy */
 	spinlock_t		lock;
 
 	/* async schedule support */
@@ -84,11 +90,6 @@
 
 	unsigned		is_tdi_rh_tt:1;	/* TDI roothub with TT */
 
-	/* glue to PCI and HCD framework */
-	struct ehci_caps __iomem *caps;
-	struct ehci_regs __iomem *regs;
-	__u32			hcs_params;	/* cached register copy */
-
 	/* irq statistics */
 #ifdef EHCI_STATS
 	struct ehci_stats	stats;
@@ -165,7 +166,7 @@
 	/* these fields are specified as 8 and 16 bit registers,
 	 * but some hosts can't perform 8 or 16 bit PCI accesses.
 	 */
-	u32	hc_capbase;
+	u32		hc_capbase;
 #define HC_LENGTH(p)		(((p)>>00)&0x00ff)	/* bits 7:0 */
 #define HC_VERSION(p)		(((p)>>16)&0xffff)	/* bits 31:16 */
 	u32		hcs_params;     /* HCSPARAMS - offset 0x4 */
@@ -273,7 +274,7 @@
 #define DBGP_ENABLED	(1<<28)
 #define DBGP_DONE	(1<<16)
 #define DBGP_INUSE	(1<<10)
-#define DBGP_ERRCODE(x)	(((x)>>7)&0x0f)
+#define DBGP_ERRCODE(x)	(((x)>>7)&0x07)
 #	define DBGP_ERR_BAD	1
 #	define DBGP_ERR_SIGNAL	2
 #define DBGP_ERROR	(1<<6)
@@ -282,11 +283,11 @@
 #define DBGP_LEN(x)	(((x)>>0)&0x0f)
 	u32	pids;
 #define DBGP_PID_GET(x)		(((x)>>16)&0xff)
-#define DBGP_PID_SET(data,tok)	(((data)<<8)|(tok));
+#define DBGP_PID_SET(data,tok)	(((data)<<8)|(tok))
 	u32	data03;
 	u32	data47;
 	u32	address;
-#define DBGP_EPADDR(dev,ep)	(((dev)<<8)|(ep));
+#define DBGP_EPADDR(dev,ep)	(((dev)<<8)|(ep))
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 376f8a0..d9883d7 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -4329,7 +4329,7 @@
 	bus->bus_name="ETRAX 100LX";
 	bus->hcpriv = hc;
 
-	/* Initalize RH to the default address.
+	/* Initialize RH to the default address.
 	   And make sure that we have no status change indication */
 	hc->rh.numports = 2;  /* The RH has two ports */
 	hc->rh.devnum = 1;
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index d309e29..a374b76 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -134,7 +134,7 @@
 
 /* This is a PIO-only HCD.  Queueing appends URBs to the endpoint's queue,
  * and may start I/O.  Endpoint queues are scanned during completion irq
- * handlers (one per packet: ACK, NAK, faults, etc) and urb cancelation.
+ * handlers (one per packet: ACK, NAK, faults, etc) and urb cancellation.
  *
  * Using an external DMA engine to copy a packet at a time could work,
  * though setup/teardown costs may be too big to make it worthwhile.
@@ -738,7 +738,7 @@
 		}
 #endif
 
-		/* port status seems wierd until after reset, so
+		/* port status seems weird until after reset, so
 		 * force the reset and make khubd clean up later.
 		 */
 		sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION)
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 5791723..a330a4b 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -23,7 +23,7 @@
  *
  *
  * The driver brings the USB functions of the MDC800 to Linux.
- * To use the Camera you must support the USB Protocoll of the camera
+ * To use the Camera you must support the USB Protocol of the camera
  * to the Kernel Node.
  * The Driver uses a misc device Node. Create it with :
  * mknod /dev/mustek c 180 32
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index cab89a9..7d21a4f 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -335,7 +335,7 @@
 
 	mts_urb_abort(desc);
 
-	return FAILURE;
+	return FAILED;
 }
 
 static int mts_scsi_host_reset (Scsi_Cmnd *srb)
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 2d76be6..94ce2a9 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -386,7 +386,7 @@
  * convention above.) I therefore have taken over REL_MISC and ABS_MISC
  * (for relative and absolute reports, respectively) for communicating
  * Proximity. Why two events? I thought it interesting to know if the
- * Proximity event occured while the tablet was in absolute or relative
+ * Proximity event occurred while the tablet was in absolute or relative
  * mode.
  *
  * Other tablets use the notion of a certain minimum stylus pressure
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 355add5..860df26 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -619,7 +619,7 @@
 		
 	if (ati_remote->outbuf)
 		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, 
-				ati_remote->inbuf, ati_remote->outbuf_dma);
+				ati_remote->outbuf, ati_remote->outbuf_dma);
 	
 	if (ati_remote->irq_urb)
 		usb_free_urb(ati_remote->irq_urb);
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 6b45a66..ab1a2a3 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -32,7 +32,7 @@
  *    Changed reset from standard USB dev reset to vendor reset
  *    Changed data sent to host from compensated to raw coordinates
  *    Eliminated vendor/product module params
- *    Performed multiple successfull tests with an EXII-5010UC
+ *    Performed multiple successful tests with an EXII-5010UC
  *
  *  1.5 02/27/2005 ddstreet@ieee.org
  *    Added module parameter to select raw or hw-calibrated coordinate reporting
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 01514b0..7038fb9 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -133,7 +133,8 @@
 				kbd->usbdev->devpath, i);
 }
 
-int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int usb_kbd_event(struct input_dev *dev, unsigned int type,
+			 unsigned int code, int value)
 {
 	struct usb_kbd *kbd = dev->private;
 
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index d605182..036c485 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -5041,7 +5041,7 @@
 		{ OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
 //		{ OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
 		{ OV511_I2C_BUS, 0x2d, 0x99 },
-		{ OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Procesing Parameter */
+		{ OV511_I2C_BUS, 0x33, 0xa0 }, /* Color Processing Parameter */
 		{ OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */
 		{ OV511_I2C_BUS, 0x38, 0x8b },
 		{ OV511_I2C_BUS, 0x39, 0x40 },
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 26aa914..42ec468 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -418,6 +418,44 @@
 
 
 
+static void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+	int i, factor = 0, filler = 0;
+
+	/* for PALETTE_YUV420P */
+	switch(pdev->vpalette)
+	{
+	case VIDEO_PALETTE_YUV420P:
+		factor = 6;
+		filler = 128;
+		break;
+	case VIDEO_PALETTE_RAW:
+		factor = 6; /* can be uncompressed YUV420P */
+		filler = 0;
+		break;
+	}
+
+	/* Set sizes in bytes */
+	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
+
+	/* Align offset, or you'll get some very weird results in
+	   YUV420 mode... x must be multiple of 4 (to get the Y's in
+	   place), and y even (or you'll mixup U & V). This is less of a
+	   problem for YUV420P.
+	 */
+	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
+	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
+
+	/* Fill buffers with gray or black */
+	for (i = 0; i < MAX_IMAGES; i++) {
+		if (pdev->image_ptr[i] != NULL)
+			memset(pdev->image_ptr[i], filler, pdev->view.size);
+	}
+}
+
+
+
 /**
    @pdev: device structure
    @width: viewport width
@@ -475,44 +513,6 @@
 }
 
 
-void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
-	int i, factor = 0, filler = 0;
-
-	/* for PALETTE_YUV420P */
-	switch(pdev->vpalette)
-	{
-	case VIDEO_PALETTE_YUV420P:
-		factor = 6;
-		filler = 128;
-		break;
-	case VIDEO_PALETTE_RAW:
-		factor = 6; /* can be uncompressed YUV420P */
-		filler = 0;
-		break;
-	}
-
-	/* Set sizes in bytes */
-	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
-	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
-
-	/* Align offset, or you'll get some very weird results in
-	   YUV420 mode... x must be multiple of 4 (to get the Y's in
-	   place), and y even (or you'll mixup U & V). This is less of a
-	   problem for YUV420P.
-	 */
-	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
-	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-
-	/* Fill buffers with gray or black */
-	for (i = 0; i < MAX_IMAGES; i++) {
-		if (pdev->image_ptr[i] != NULL)
-			memset(pdev->image_ptr[i], filler, pdev->view.size);
-	}
-}
-
-
-
 /* BRIGHTNESS */
 
 int pwc_get_brightness(struct pwc_device *pdev)
@@ -949,7 +949,7 @@
 	return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
 }
 
-int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
+static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
 {
 	unsigned char buf[2];
 	int ret;
@@ -1100,7 +1100,7 @@
 	unsigned char buf[4];
 	
 	/* set new relative angle; angles are expressed in degrees * 100,
-	   but cam as .5 degree resolution, hence devide by 200. Also
+	   but cam as .5 degree resolution, hence divide by 200. Also
 	   the angle must be multiplied by 64 before it's send to
 	   the cam (??)
 	 */
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 100a5a4..cca47f4 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -129,7 +129,7 @@
        int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
 static int power_save = 0;
 static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
-       int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
 static struct {
 	int type;
 	char serial_number[30];
@@ -272,7 +272,7 @@
 		return -ENXIO;
 	}
 #endif	
-	/* Allocate Isochronuous pipe buffers */
+	/* Allocate Isochronous pipe buffers */
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		if (pdev->sbuf[i].data == NULL) {
 			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
@@ -322,7 +322,7 @@
 	  case 730:
 	  case 740:
 	  case 750:
-	    Trace(TRACE_MEMORY,"private_data(%Zd)\n",sizeof(struct pwc_dec23_private));
+	    Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
 	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);	/* Timon & Kiara */
 	    break;
 	  case 645:
@@ -850,7 +850,7 @@
 	
 	if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
 		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
-		return -ENFILE; /* Odd error, that should be noticable */
+		return -ENFILE; /* Odd error, that should be noticeable */
 	}
 
 	/* Set alternate interface */
@@ -1179,7 +1179,7 @@
 	DECLARE_WAITQUEUE(wait, current);
         int bytes_to_read;
 
-	Trace(TRACE_READ, "video_read(0x%p, %p, %Zd) called.\n", vdev, buf, count);
+	Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count);
 	if (vdev == NULL)
 		return -EFAULT;
 	pdev = vdev->priv;
@@ -2128,7 +2128,7 @@
 	if (leds[1] >= 0)
 		led_off = leds[1];
 
-	/* Big device node whoopla. Basicly, it allows you to assign a
+	/* Big device node whoopla. Basically, it allows you to assign a
 	   device node (/dev/videoX) to a camera, based on its type
 	   & serial number. The format is [type[.serialnumber]:]node.
 
diff --git a/drivers/usb/media/pwc/pwc-ioctl.h b/drivers/usb/media/pwc/pwc-ioctl.h
index 65805ea..5f9cb08 100644
--- a/drivers/usb/media/pwc/pwc-ioctl.h
+++ b/drivers/usb/media/pwc/pwc-ioctl.h
@@ -75,7 +75,7 @@
 #define PWC_FPS_SNAPSHOT	0x00400000
 
 
-/* structure for transfering x & y coordinates */
+/* structure for transferring x & y coordinates */
 struct pwc_coord
 {
 	int x, y;		/* guess what */
diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h
index 53b516d..267869d 100644
--- a/drivers/usb/media/pwc/pwc.h
+++ b/drivers/usb/media/pwc/pwc.h
@@ -226,9 +226,8 @@
 extern "C" {
 #endif
 
-/* Global variables */
+/* Global variable */
 extern int pwc_trace;
-extern int pwc_preferred_compression;
 
 /** functions in pwc-if.c */
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
@@ -243,8 +242,6 @@
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
-/* Calculate the number of bytes per image (not frame) */
-extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
 
 /* Various controls; should be obvious. Value 0..65535, or < 0 on error */
 extern int pwc_get_brightness(struct pwc_device *pdev);
@@ -256,7 +253,6 @@
 extern int pwc_get_saturation(struct pwc_device *pdev);
 extern int pwc_set_saturation(struct pwc_device *pdev, int value);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
-extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
 
 /* Power down or up the camera; not supported by all models */
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index 898401c..31d5740 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -429,7 +429,7 @@
 }
 
 
-int 
+static int 
 sn9c102_i2c_try_write(struct sn9c102_device* cam,
                       struct sn9c102_sensor* sensor, u8 address, u8 value)
 {
@@ -785,7 +785,7 @@
 }
 
 
-int sn9c102_stream_interrupt(struct sn9c102_device* cam)
+static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
 {
 	int err = 0;
 
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index 16f7483..6a7adeb 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -145,8 +145,6 @@
 */
 
 /* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
-                                 u8 address, u8 value);
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
                                 u8 address);
 
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index dd4580c..7d06105 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -859,7 +859,7 @@
 		info ("udev is NULL.");
 	}
 
-	/* allocate memory for our device state and intialize it */
+	/* allocate memory for our device state and initialize it */
 
 	dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 57b82d5..2fd1226 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -983,7 +983,7 @@
 				msgcount++;
 				if (msgcount < 500)
 					printk(KERN_ERR
-						"sisusbvga[%d]: Wrote %Zd of "
+						"sisusbvga[%d]: Wrote %zd of "
 						"%d bytes, error %d\n",
 						sisusb->minor, *bytes_written,
 						length, ret);
@@ -3105,6 +3105,7 @@
 static struct usb_device_id sisusb_table [] = {
 	{ USB_DEVICE(0x0711, 0x0900) },
 	{ USB_DEVICE(0x182d, 0x021c) },
+	{ USB_DEVICE(0x182d, 0x0269) },
 	{ }
 };
 
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index a02be79..d976790 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -1388,11 +1388,11 @@
 	if (netif_running(pegasus->net)) {
 		pegasus->rx_urb->status = 0;
 		pegasus->rx_urb->actual_length = 0;
-		read_bulk_callback(pegasus->rx_urb, 0);
+		read_bulk_callback(pegasus->rx_urb, NULL);
 
 		pegasus->intr_urb->status = 0;
 		pegasus->intr_urb->actual_length = 0;
-		intr_callback(pegasus->intr_urb, 0);
+		intr_callback(pegasus->intr_urb, NULL);
 
 		queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
 					CARRIER_CHECK_DELAY);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index bbaef04..f6bc6b3 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -1,6 +1,6 @@
 /*
  * USB Networking Links
- * Copyright (C) 2000-2003 by David Brownell <dbrownell@users.sourceforge.net>
+ * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
  * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
  * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
@@ -210,6 +210,7 @@
 #		define EVENT_RX_HALT	1
 #		define EVENT_RX_MEMORY	2
 #		define EVENT_STS_SPLIT	3
+#		define EVENT_LINK_RESET	4
 };
 
 // device-specific info used by the driver
@@ -243,6 +244,9 @@
 	/* for status polling */
 	void	(*status)(struct usbnet *, struct urb *);
 
+	/* link reset handling, called from defer_kevent */
+	int	(*link_reset)(struct usbnet *);
+
 	/* fixup rx packet (strip framing) */
 	int	(*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
 
@@ -304,6 +308,7 @@
 static u32 usbnet_get_link (struct net_device *);
 static u32 usbnet_get_msglevel (struct net_device *);
 static void usbnet_set_msglevel (struct net_device *, u32);
+static void defer_kevent (struct usbnet *, int);
 
 /* mostly for PDA style devices, which are always connected if present */
 static int always_connected (struct usbnet *dev)
@@ -426,7 +431,7 @@
 	dev->stats.rx_bytes += skb->len;
 
 	if (netif_msg_rx_status (dev))
-		devdbg (dev, "< rx, len %zd, type 0x%x",
+		devdbg (dev, "< rx, len %zu, type 0x%x",
 			skb->len + sizeof (struct ethhdr), skb->protocol);
 	memset (skb->cb, 0, sizeof (struct skb_data));
 	status = netif_rx (skb);
@@ -501,6 +506,7 @@
 #define AX_CMD_WRITE_MULTI_FILTER	0x16
 #define AX_CMD_READ_NODE_ID		0x17
 #define AX_CMD_READ_PHY_ID		0x19
+#define AX_CMD_READ_MEDIUM_STATUS	0x1a
 #define AX_CMD_WRITE_MEDIUM_MODE	0x1b
 #define AX_CMD_READ_MONITOR_MODE	0x1c
 #define AX_CMD_WRITE_MONITOR_MODE	0x1d
@@ -515,11 +521,14 @@
 #define AX_MONITOR_MAGIC		0x04
 #define AX_MONITOR_HSFS			0x10
 
+/* AX88172 Medium Status Register values */
+#define AX_MEDIUM_FULL_DUPLEX		0x02
+#define AX_MEDIUM_TX_ABORT_ALLOW	0x04
+#define AX_MEDIUM_FLOW_CONTROL_EN	0x10
+
 #define AX_MCAST_FILTER_SIZE		8
 #define AX_MAX_MCAST			64
 
-#define AX_INTERRUPT_BUFSIZE		8
-
 #define AX_EEPROM_LEN			0x40
 
 #define AX_SWRESET_CLEAR		0x00
@@ -535,15 +544,33 @@
 #define AX88772_IPG1_DEFAULT		0x0c
 #define AX88772_IPG2_DEFAULT		0x12
 
+#define AX88772_MEDIUM_FULL_DUPLEX	0x0002
+#define AX88772_MEDIUM_RESERVED		0x0004
+#define AX88772_MEDIUM_RX_FC_ENABLE	0x0010
+#define AX88772_MEDIUM_TX_FC_ENABLE	0x0020
+#define AX88772_MEDIUM_PAUSE_FORMAT	0x0080
+#define AX88772_MEDIUM_RX_ENABLE	0x0100
+#define AX88772_MEDIUM_100MB		0x0200
+#define AX88772_MEDIUM_DEFAULT	\
+	(AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
+	 AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
+	 AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+
 #define AX_EEPROM_MAGIC			0xdeadbeef
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct ax8817x_data {
 	u8 multi_filter[AX_MCAST_FILTER_SIZE];
-	struct urb *int_urb;
-	u8 *int_buf;
 };
 
+struct ax88172_int_data {
+	u16 res1;
+	u8 link;
+	u16 res2;
+	u8 status;
+	u16 res3;
+} __attribute__ ((packed));
+
 static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 			    u16 size, void *data)
 {
@@ -586,25 +613,23 @@
 	usb_free_urb(urb);
 }
 
-static void ax8817x_interrupt_complete(struct urb *urb, struct pt_regs *regs)
+static void ax8817x_status(struct usbnet *dev, struct urb *urb)
 {
-	struct usbnet *dev = (struct usbnet *)urb->context;
-	struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+	struct ax88172_int_data *event;
 	int link;
 
-	if (urb->status < 0) {
-		devdbg(dev,"ax8817x_interrupt_complete() failed with %d",
-			urb->status);
-	} else {
-		link = data->int_buf[2] & 0x01;
-		if (netif_carrier_ok(dev->net) != link) {
-			if (link)
-				netif_carrier_on(dev->net);
-			else
-				netif_carrier_off(dev->net);
-			devdbg(dev, "ax8817x - Link Status is: %d", link);
-		}
-		usb_submit_urb(data->int_urb, GFP_ATOMIC);
+	if (urb->actual_length < 8)
+		return;
+
+	event = urb->transfer_buffer;
+	link = event->link & 0x01;
+	if (netif_carrier_ok(dev->net) != link) {
+		if (link) {
+			netif_carrier_on(dev->net);
+			defer_kevent (dev, EVENT_LINK_RESET );
+		} else
+			netif_carrier_off(dev->net);
+		devdbg(dev, "ax8817x - Link Status is: %d", link);
 	}
 }
 
@@ -711,6 +736,20 @@
 	ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
 }
 
+static int ax88172_link_reset(struct usbnet *dev)
+{
+	u16 lpa;
+	u8 mode;
+
+	mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
+	lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
+	if (lpa & LPA_DUPLEX)
+		mode |= AX_MEDIUM_FULL_DUPLEX;
+	ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+
+	return 0;
+}
+
 static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -824,35 +863,13 @@
 	void *buf;
 	int i;
 	unsigned long gpio_bits = dev->driver_info->data;
-	struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
 
 	get_endpoints(dev,intf);
 
-	if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == NULL) {
-		dbg ("%s: cannot allocate interrupt URB",
-			dev->net->name);
-		ret = -ENOMEM;
-		goto out1;
-	}
-	
-	if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
-		dbg ("%s: cannot allocate memory for interrupt buffer",
-			dev->net->name);
-		ret = -ENOMEM;
-		goto out1;
-	}
-	memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
-
-	usb_fill_int_urb (data->int_urb, dev->udev,
-		usb_rcvintpipe (dev->udev, 1),
-		data->int_buf, AX_INTERRUPT_BUFSIZE,
-		ax8817x_interrupt_complete, dev,
-		dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
-
 	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
 	if(!buf) {
 		ret = -ENOMEM;
-		goto out2;
+		goto out1;
 	}
 
 	/* Toggle the GPIOs in a manufacturer/model specific way */
@@ -860,32 +877,32 @@
 		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
 					(gpio_bits >> (i * 8)) & 0xff, 0, 0,
 					buf)) < 0)
-			goto out3;
+			goto out2;
 		msleep(5);
 	}
 
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) {
 		dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
 	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) {
 		dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
-		goto out3;
+		goto out2;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
 	/* Get the PHY id */
 	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
 		dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
-		goto out3;
+		goto out2;
 	} else if (ret < 2) {
 		/* this should always return 2 bytes */
 		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
 		ret = -EIO;
-		goto out3;
+		goto out2;
 	}
 
 	/* Initialize MII structure */
@@ -899,36 +916,18 @@
 	dev->net->set_multicast_list = ax8817x_set_multicast;
 	dev->net->ethtool_ops = &ax8817x_ethtool_ops;
 
-	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
-			cpu_to_le16(BMCR_RESET));
+	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
 	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-			cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400));
+		ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
 	mii_nway_restart(&dev->mii);
 
-	if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
-		dbg("Failed to submit interrupt URB: %02x", ret);
-		goto out2;
-	}
-
 	return 0;
-out3:
-	kfree(buf);
 out2:
-	kfree(data->int_buf);
+	kfree(buf);
 out1:
-	usb_free_urb(data->int_urb);
 	return ret;
 }
 
-static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf)
-{
-	struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
-
-	usb_kill_urb(data->int_urb);
-	usb_free_urb(data->int_urb);
-	kfree(data->int_buf);
-}
-
 static struct ethtool_ops ax88772_ethtool_ops = {
 	.get_drvinfo		= ax8817x_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
@@ -946,64 +945,44 @@
 {
 	int ret;
 	void *buf;
-	struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
 
 	get_endpoints(dev,intf);
 
-	if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
-		dbg ("Cannot allocate interrupt URB");
-		ret = -ENOMEM;
-		goto out1;
-	}
-	
-	if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
-		dbg ("Cannot allocate memory for interrupt buffer");
-		ret = -ENOMEM;
-		goto out1;
-	}
-	memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
-
-	usb_fill_int_urb (data->int_urb, dev->udev,
-		usb_rcvintpipe (dev->udev, 1),
-		data->int_buf, AX_INTERRUPT_BUFSIZE,
-		ax8817x_interrupt_complete, dev,
-		dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
-
 	buf = kmalloc(6, GFP_KERNEL);
 	if(!buf) {
 		dbg ("Cannot allocate memory for buffer");
 		ret = -ENOMEM;
-		goto out2;
+		goto out1;
 	}
 
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
 				     0x00B0, 0, 0, buf)) < 0)
-		goto out3;
+		goto out2;
 
 	msleep(5);
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
 		dbg("Select PHY #1 failed: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 0, 0, buf)) < 0) {
 		dbg("Failed to power down internal PHY: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	msleep(150);
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 0, 0, buf)) < 0) {
 		dbg("Failed to perform software reset: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	msleep(150);
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
 		dbg("Failed to set Internal/External PHY reset control: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	msleep(150);
@@ -1011,27 +990,27 @@
 	     ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0,
 			       buf)) < 0) {
 		dbg("Failed to reset RX_CTL: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
 	if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
 		dbg("Failed to read MAC address: %d", ret);
-		goto out3;
+		goto out2;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, buf)) < 0) {
 		dbg("Enabling software MII failed: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	if (((ret =
 	      ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
 	    || (*((u16 *)buf) != 0x003b)) {
 		dbg("Read PHY register 2 must be 0x3b00: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	/* Initialize MII structure */
@@ -1044,26 +1023,26 @@
 	/* Get the PHY id */
 	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
 		dbg("Error reading PHY ID: %02x", ret);
-		goto out3;
+		goto out2;
 	} else if (ret < 2) {
 		/* this should always return 2 bytes */
 		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
 		    ret);
 		ret = -EIO;
-		goto out3;
+		goto out2;
 	}
 	dev->mii.phy_id = *((u8 *)buf + 1);
 
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
 		dbg("Set external PHY reset pin level: %d", ret);
-		goto out3;
+		goto out2;
 	}
 	msleep(150);
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
 		dbg("Set Internal/External PHY reset control: %d", ret);
-		goto out3;
+		goto out2;
 	}
 	msleep(150);
 
@@ -1071,25 +1050,24 @@
 	dev->net->set_multicast_list = ax8817x_set_multicast;
 	dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
-			cpu_to_le16(BMCR_RESET));
+	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
 	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-			cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA));
+			ADVERTISE_ALL | ADVERTISE_CSMA);
 	mii_nway_restart(&dev->mii);
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0x0336, 0, 0, buf)) < 0) {
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
 		dbg("Write medium mode register: %d", ret);
-		goto out3;
+		goto out2;
 	}
 
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
 		dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
-		goto out3;
+		goto out2;
 	}
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
 		dbg("Failed to set hardware MII: %02x", ret);
-		goto out3;
+		goto out2;
 	}
 
 	/* Set RX_CTL to default values with 2k buffer, and enable cactus */
@@ -1097,25 +1075,16 @@
 	     ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
 			       buf)) < 0) {
 		dbg("Reset RX_CTL failed: %d", ret);
-		goto out3;
-	}
-
-	if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
-		dbg("Failed to submit interrupt URB: %02x", ret);
-		goto out3;
+		goto out2;
 	}
 
 	kfree(buf);
 
 	return 0;
 
-out3:
-	kfree(buf);
 out2:
-	kfree(data->int_buf);
+	kfree(buf);
 out1:
-	usb_free_urb(data->int_urb);
-
 	return ret;
 }
 
@@ -1213,10 +1182,29 @@
 	return skb;
 }
 
+static int ax88772_link_reset(struct usbnet *dev)
+{
+	u16 lpa;
+	u16 mode;
+
+	mode = AX88772_MEDIUM_DEFAULT;
+	lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
+
+	if ((lpa & LPA_DUPLEX) == 0)
+		mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
+	if ((lpa & LPA_100) == 0)
+		mode &= ~AX88772_MEDIUM_100MB;
+	ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+
+	return 0;
+}
+
 static const struct driver_info ax8817x_info = {
 	.description = "ASIX AX8817x USB 2.0 Ethernet",
 	.bind = ax8817x_bind,
-	.unbind = ax8817x_unbind,
+	.status = ax8817x_status,
+	.link_reset = ax88172_link_reset,
+	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
 	.data = 0x00130103,
 };
@@ -1224,7 +1212,9 @@
 static const struct driver_info dlink_dub_e100_info = {
 	.description = "DLink DUB-E100 USB Ethernet",
 	.bind = ax8817x_bind,
-	.unbind = ax8817x_unbind,
+	.status = ax8817x_status,
+	.link_reset = ax88172_link_reset,
+	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
 	.data = 0x009f9d9f,
 };
@@ -1232,7 +1222,9 @@
 static const struct driver_info netgear_fa120_info = {
 	.description = "Netgear FA-120 USB Ethernet",
 	.bind = ax8817x_bind,
-	.unbind = ax8817x_unbind,
+	.status = ax8817x_status,
+	.link_reset = ax88172_link_reset,
+	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
 	.data = 0x00130103,
 };
@@ -1240,7 +1232,9 @@
 static const struct driver_info hawking_uf200_info = {
 	.description = "Hawking UF200 USB Ethernet",
 	.bind = ax8817x_bind,
-	.unbind = ax8817x_unbind,
+	.status = ax8817x_status,
+	.link_reset = ax88172_link_reset,
+	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
 	.data = 0x001f1d1f,
 };
@@ -1248,7 +1242,9 @@
 static const struct driver_info ax88772_info = {
 	.description = "ASIX AX88772 USB 2.0 Ethernet",
 	.bind = ax88772_bind,
-	.unbind = ax8817x_unbind,
+	.status = ax8817x_status,
+	.link_reset = ax88772_link_reset,
+	.reset = ax88772_link_reset,
 	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
 	.rx_fixup = ax88772_rx_fixup,
 	.tx_fixup = ax88772_tx_fixup,
@@ -2661,7 +2657,7 @@
  * All known Zaurii lie about their standards conformance.  Most lie by
  * saying they support CDC Ethernet.  Some lie and say they support CDC
  * MDLM (as if for access to cell phone modems).  Someone, please beat 
- * on Sharp for a while with a cluestick.
+ * on Sharp (and other such vendors) for a while with a cluestick.
  *
  *-------------------------------------------------------------------------*/
 
@@ -2714,13 +2710,6 @@
 };
 #define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)
 
-static const struct driver_info	zaurus_pxa_mdlm_info = {
-	.description =	"Sharp Zaurus, PXA-255 based",
-	.flags =	FLAG_FRAMING_Z,
-	.check_connect = always_connected,
-	.tx_fixup = 	zaurus_tx_fixup,
-};
-
 static const struct driver_info	olympus_mxl_info = {
 	.description =	"Olympus R1000",
 	.flags =	FLAG_FRAMING_Z,
@@ -2731,6 +2720,133 @@
 };
 #define	OLYMPUS_MXL_INFO	((unsigned long)&olympus_mxl_info)
 
+
+/* Some more recent products using Lineo/Belcarra code will wrongly claim
+ * CDC MDLM conformance.  They aren't conformant:  data endpoints live
+ * in the control interface, there's no data interface, and it's not used
+ * to talk to a cell phone radio.  But at least we can detect these two
+ * pseudo-classes, rather than growing this product list with entries for
+ * each new nonconformant product (sigh).
+ */
+static const u8 safe_guid[16] = {
+	0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+	0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+};
+static const u8 blan_guid[16] = {
+	0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
+	0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
+};
+
+static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
+{
+	u8				*buf = intf->cur_altsetting->extra;
+	int				len = intf->cur_altsetting->extralen;
+	struct usb_cdc_mdlm_desc	*desc = NULL;
+	struct usb_cdc_mdlm_detail_desc	*detail = NULL;
+
+	while (len > 3) {
+		if (buf [1] != USB_DT_CS_INTERFACE)
+			goto next_desc;
+
+		/* use bDescriptorSubType, and just verify that we get a
+		 * "BLAN" (or "SAFE") descriptor.
+		 */
+		switch (buf [2]) {
+		case USB_CDC_MDLM_TYPE:
+			if (desc) {
+				dev_dbg (&intf->dev, "extra MDLM\n");
+				goto bad_desc;
+			}
+			desc = (void *) buf;
+			if (desc->bLength != sizeof *desc) {
+				dev_dbg (&intf->dev, "MDLM len %u\n",
+					desc->bLength);
+				goto bad_desc;
+			}
+			/* expect bcdVersion 1.0, ignore */
+			if (memcmp(&desc->bGUID, blan_guid, 16)
+				    || memcmp(&desc->bGUID, blan_guid, 16) ) {
+				/* hey, this one might _really_ be MDLM! */
+				dev_dbg (&intf->dev, "MDLM guid\n");
+				goto bad_desc;
+			}
+			break;
+		case USB_CDC_MDLM_DETAIL_TYPE:
+			if (detail) {
+				dev_dbg (&intf->dev, "extra MDLM detail\n");
+				goto bad_desc;
+			}
+			detail = (void *) buf;
+			switch (detail->bGuidDescriptorType) {
+			case 0:			/* "SAFE" */
+				if (detail->bLength != (sizeof *detail + 2))
+					goto bad_detail;
+				break;
+			case 1:			/* "BLAN" */
+				if (detail->bLength != (sizeof *detail + 3))
+					goto bad_detail;
+				break;
+			default:
+				goto bad_detail;
+			}
+
+			/* assuming we either noticed BLAN already, or will
+			 * find it soon, there are some data bytes here:
+			 *  - bmNetworkCapabilities (unused)
+			 *  - bmDataCapabilities (bits, see below)
+			 *  - bPad (ignored, for PADAFTER -- BLAN-only)
+			 * bits are:
+			 *  - 0x01 -- Zaurus framing (add CRC)
+			 *  - 0x02 -- PADBEFORE
+			 *  - 0x04 -- PADAFTER
+			 *  - 0x08 -- "fermat" packet mangling (for hw bugs)
+			 */
+			if (detail->bDetailData[1] != 0x01) {
+				/* bmDataCapabilites == 0 would be fine too,
+				 * but framing is minidriver-coupled for now.
+				 */
+bad_detail:
+				dev_dbg (&intf->dev,
+						"bad MDLM detail, %d %d %d\n",
+						detail->bLength,
+						detail->bDetailData[0],
+						detail->bDetailData[2]);
+				goto bad_desc;
+			}
+			break;
+		}
+next_desc:
+		len -= buf [0];	/* bLength */
+		buf += buf [0];
+	}
+
+	if (!desc || !detail) {
+		dev_dbg (&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
+			desc ? "" : "func ",
+			detail ? "" : "detail ");
+		goto bad_desc;
+	}
+
+	/* There's probably a CDC Ethernet descriptor there, but we can't
+	 * rely on the Ethernet address it provides since not all vendors
+	 * bother to make it unique.  Likewise there's no point in tracking
+	 * of the CDC event notifications.
+	 */
+	return get_endpoints (dev, intf);
+
+bad_desc:
+	dev_info (&dev->udev->dev, "unsupported MDLM descriptors\n");
+	return -ENODEV;
+}
+
+static const struct driver_info	bogus_mdlm_info = {
+	.description =	"pseudo-MDLM (BLAN) device",
+	.flags =	FLAG_FRAMING_Z,
+	.check_connect = always_connected,
+	.tx_fixup = 	zaurus_tx_fixup,
+	.bind =		blan_mdlm_bind,
+};
+
 #else
 
 /* blacklist all those devices */
@@ -3307,6 +3423,19 @@
 		}
 	}
 
+	if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
+		struct driver_info 	*info = dev->driver_info;
+		int			retval = 0;
+
+		clear_bit (EVENT_LINK_RESET, &dev->flags);
+		if(info->link_reset && (retval = info->link_reset(dev)) < 0) {
+			devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s",
+				retval,
+				dev->udev->bus->bus_name, dev->udev->devpath,
+				info->description);
+		}
+	}
+
 	if (dev->flags)
 		devdbg (dev, "kevent done, flags = 0x%lx",
 			dev->flags);
@@ -3942,6 +4071,9 @@
 	USB_DEVICE (0x8086, 0x07d3),	// "blob" bootloader
 	.driver_info =	(unsigned long) &blob_info,
 }, {
+	USB_DEVICE (0x22b8, 0x600c),	// USBNET Motorola E680
+	.driver_info =	(unsigned long) &linuxdev_info,
+}, {
 	// Linux Ethernet/RNDIS gadget on pxa210/25x/26x
 	// e.g. Gumstix, current OpenZaurus, ...
 	USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
@@ -4020,30 +4152,14 @@
 },
 
 #ifdef	CONFIG_USB_ZAURUS
-	/* at least some (reports vary) PXA units have very different
-	 * lies about their standards support:  they claim to be cell
-	 * phones giving direct radio access (which they aren't).
+	/* At least some (reports vary) PXA units have very different lies
+	 * about their standards support:  they claim to be cell phones with
+	 * direct access to their radios.  (They don't conform to CDC MDLM.)
 	 */
 {
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-		 | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor               = 0x04DD,
-	/* Sharp ROM v1.32 */
-	.idProduct		= 0x8006,	/* SL-5600 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM,
-	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
-	.driver_info 		= (unsigned long) &zaurus_pxa_mdlm_info,
-}, {
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-		 | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor               = 0x04DD,
-	/* reported with some C860 units */
-	.idProduct              = 0x9031,	/* C-860 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM,
-	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
-	.driver_info 		= (unsigned long) &zaurus_pxa_mdlm_info,
+	USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
+			USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &bogus_mdlm_info,
 },
 #endif
 
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index c81cd0a..341ae5f 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -45,7 +45,7 @@
 MODULE_DEVICE_TABLE(usb, zd1201_table);
 
 
-int zd1201_fw_upload(struct usb_device *dev, int apfw)
+static int zd1201_fw_upload(struct usb_device *dev, int apfw)
 {
 	const struct firmware *fw_entry;
 	char* data;
@@ -111,7 +111,7 @@
 	return err;
 }
 
-void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
+static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
 {
 	struct zd1201 *zd = urb->context;
 
@@ -142,7 +142,8 @@
 
 	total: 4 + 2 + 2 + 2 + 2 + 4 = 16
 */
-int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, int parm1, int parm2)
+static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
+			int parm1, int parm2)
 {
 	unsigned char *command;
 	int ret;
@@ -175,15 +176,15 @@
 }
 
 /* Callback after sending out a packet */
-void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
+static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
 {
 	struct zd1201 *zd = urb->context;
 	netif_wake_queue(zd->dev);
 	return;
 }
 
-/* Incomming data */
-void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
+/* Incoming data */
+static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
 {
 	struct zd1201 *zd = urb->context;
 	int free = 0;
@@ -613,7 +614,7 @@
 	return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));
 }
 
-int zd1201_drvr_start(struct zd1201 *zd)
+static int zd1201_drvr_start(struct zd1201 *zd)
 {
 	int err, i;
 	short max;
@@ -771,7 +772,7 @@
 /*
 	RFC 1042 encapsulates Ethernet frames in 802.11 frames
 	by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0
-	(0x00, 0x00, 0x00). Zd requires an additionnal padding, copy
+	(0x00, 0x00, 0x00). Zd requires an additional padding, copy
 	of ethernet addresses, length of the standard RFC 1042 packet
 	and a command byte (which is nul for tx).
 	
@@ -1097,7 +1098,7 @@
 
 /*	Little bit of magic here: we only get the quality if we poll
  *	for it, and we never get an actual request to trigger such
- *	a poll. Therefore we 'asume' that the user will soon ask for
+ *	a poll. Therefore we 'assume' that the user will soon ask for
  *	the stats after asking the bssid.
  */
 static int zd1201_get_wap(struct net_device *dev,
@@ -1107,7 +1108,7 @@
 	unsigned char buffer[6];
 
 	if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
-		/* Unfortunatly the quality and noise reported is useless.
+		/* Unfortunately the quality and noise reported is useless.
 		   they seem to be accumulators that increase until you
 		   read them, unless we poll on a fixed interval we can't
 		   use them
@@ -1739,7 +1740,8 @@
 	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
 };
 
-int zd1201_probe(struct usb_interface *interface, const struct usb_device_id *id)
+static int zd1201_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
 {
 	struct zd1201 *zd;
 	struct usb_device *usb;
@@ -1851,7 +1853,7 @@
 	return err;
 }
 
-void zd1201_disconnect(struct usb_interface *interface)
+static void zd1201_disconnect(struct usb_interface *interface)
 {
 	struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface);
 	struct hlist_node *node, *node2;
@@ -1882,7 +1884,7 @@
 	kfree(zd);
 }
 
-struct usb_driver zd1201_usb = {
+static struct usb_driver zd1201_usb = {
 	.owner = THIS_MODULE,
 	.name = "zd1201",
 	.probe = zd1201_probe,
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index b869076..bc798ed 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -53,6 +53,15 @@
 	  support" be compiled as a module for this driver to be used
 	  properly.
 
+config USB_SERIAL_AIRPRIME
+	tristate "USB AirPrime CDMA Wireless Driver"
+	depends on USB_SERIAL
+	help
+	  Say Y here if you want to use a AirPrime CDMA Wireless PC card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called airprime.
+
 config USB_SERIAL_BELKIN
 	tristate "USB Belkin and Peracom Single Port Serial Driver"
 	depends on USB_SERIAL
@@ -395,6 +404,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pl2303.
 
+config USB_SERIAL_HP4X
+        tristate "USB HP4x Calculators support"
+        depends on USB_SERIAL
+        help
+          Say Y here if you want to use an Hewlett-Packard 4x Calculator.
+
+          To compile this driver as a module, choose M here: the
+          module will be called hp4x.
+
 config USB_SERIAL_SAFE
 	tristate "USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)"
 	depends on USB_SERIAL && EXPERIMENTAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 351b818..d56ff6d 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -11,6 +11,7 @@
 
 usbserial-objs	:= usb-serial.o generic.o bus.o $(usbserial-obj-y)
 
+obj-$(CONFIG_USB_SERIAL_AIRPRIME)		+= airprime.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)			+= belkin_sa.o
 obj-$(CONFIG_USB_SERIAL_CP2101)			+= cp2101.o
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)		+= cyberjack.o
@@ -21,6 +22,7 @@
 obj-$(CONFIG_USB_SERIAL_EMPEG)			+= empeg.o
 obj-$(CONFIG_USB_SERIAL_FTDI_SIO)		+= ftdi_sio.o
 obj-$(CONFIG_USB_SERIAL_GARMIN)			+= garmin_gps.o
+obj-$(CONFIG_USB_SERIAL_HP4X)			+= hp4x.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
 obj-$(CONFIG_USB_SERIAL_IPW)			+= ipw.o
 obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
new file mode 100644
index 0000000..a4ce000
--- /dev/null
+++ b/drivers/usb/serial/airprime.c
@@ -0,0 +1,63 @@
+/*
+ * AirPrime CDMA Wireless Serial USB driver
+ *
+ * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0xf3d, 0x0112) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver airprime_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"airprime",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
+static struct usb_serial_device_type airprime_device = {
+	.owner =		THIS_MODULE,
+	.name =			"airprime",
+	.id_table =		id_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		NUM_DONT_CARE,
+	.num_bulk_out =		NUM_DONT_CARE,
+	.num_ports =		1,
+};
+
+static int __init airprime_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&airprime_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&airprime_driver);
+	if (retval)
+		usb_serial_deregister(&airprime_device);
+	return retval;
+}
+
+static void __exit airprime_exit(void)
+{
+	usb_deregister(&airprime_driver);
+	usb_serial_deregister(&airprime_device);
+}
+
+module_init(airprime_init);
+module_exit(airprime_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index d165f42..f34a9bb 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -16,6 +16,14 @@
  * See http://geocities.com/i0xox0i for information on this driver and the
  * earthmate usb device.
  *
+ *  Lonnie Mendez <dignome@gmail.com>
+ *  4-29-2005
+ *	Fixed problem where setting or retreiving the serial config would fail with
+ * 	EPIPE.  Removed CRTS toggling so the driver behaves more like other usbserial
+ * 	adapters.  Issued new interval of 1ms instead of the default 10ms.  As a
+ * 	result, transfer speed has been substantially increased.  From avg. 850bps to
+ * 	avg. 3300bps.  initial termios has also been modified.  Cleaned up code and
+ * 	formatting issues so it is more readable.  Replaced the C++ style comments.
  *
  *  Lonnie Mendez <dignome@gmail.com>
  *  12-15-2004
@@ -32,12 +40,6 @@
  *  10-2003
  *	Driver first released.
  *
- *
- * Long Term TODO:
- *	Improve transfer speeds - both read/write are somewhat slow
- *   at this point.
- *      Improve debugging.  Show modem line status with debug output and
- *   implement filtering for certain data as a module parameter.
  */
 
 /* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */
@@ -72,11 +74,12 @@
 	static int debug;
 #endif
 static int stats;
+static int interval;
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.08"
+#define DRIVER_VERSION "v1.09"
 #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
 #define DRIVER_DESC "Cypress USB to Serial Driver"
 
@@ -130,7 +133,6 @@
 	char prev_status, diff_status;	   /* used for TIOCMIWAIT */
 	/* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
 	struct termios tmp_termios; 	   /* stores the old termios settings */
-	char calledfromopen;		   /* used when issuing lines on open - fixes rts drop bug */
 };
 
 /* write buffer structure */
@@ -168,10 +170,8 @@
 static void		  cypress_buf_clear(struct cypress_buf *cb);
 static unsigned int	  cypress_buf_data_avail(struct cypress_buf *cb);
 static unsigned int	  cypress_buf_space_avail(struct cypress_buf *cb);
-static unsigned int	  cypress_buf_put(struct cypress_buf *cb, const char *buf,
-					  unsigned int count);
-static unsigned int	  cypress_buf_get(struct cypress_buf *cb, char *buf,
-					  unsigned int count);
+static unsigned int	  cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count);
+static unsigned int	  cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
 
 
 static struct usb_serial_device_type cypress_earthmate_device = {
@@ -234,14 +234,13 @@
  *****************************************************************************/
 
 
-/* This function can either set or retreive the current serial line settings */
+/* This function can either set or retrieve the current serial line settings */
 static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
 				   int parity_enable, int parity_type, int reset, int cypress_request_type)
 {
-	int i, n_baud_rate = 0, retval = 0;
+	int new_baudrate = 0, retval = 0, tries = 0;
 	struct cypress_private *priv;
-	__u8 feature_buffer[5];
-	__u8 config;
+	__u8 feature_buffer[8];
 	unsigned long flags;
 
 	dbg("%s", __FUNCTION__);
@@ -256,7 +255,8 @@
  			 * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
 			 * firmware or not), if you need to modify this speed setting for your own
 			 * project please add your own chiptype and modify the code likewise.  The
-			 * Cypress HID->COM device will work successfully up to 115200bps.
+			 * Cypress HID->COM device will work successfully up to 115200bps (but the
+			 * actual throughput is around 3kBps).
 			 */
 			if (baud_mask != priv->cbr_mask) {
 				dbg("%s - baud rate is changing", __FUNCTION__);
@@ -265,109 +265,114 @@
 					 * but are not used with NMEA and SiRF protocols */
 					
 					if ( (baud_mask == B300) || (baud_mask == B600) ) {
-						err("%s - failed setting baud rate, unsupported speed (default to 4800)",
+						err("%s - failed setting baud rate, unsupported speed",
 						    __FUNCTION__);
-						n_baud_rate = 4800;
-					} else if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
-						err("%s - failed setting baud rate, unsupported speed (default to 4800)",
+						new_baudrate = priv->baud_rate;
+					} else if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+						err("%s - failed setting baud rate, unsupported speed",
 						    __FUNCTION__);
-						n_baud_rate = 4800;
+						new_baudrate = priv->baud_rate;
 					}
 				} else if (priv->chiptype == CT_CYPHIDCOM) {
-					if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
-						err("%s - failed setting baud rate, unsupported speed (default to 4800)",
+					if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+						err("%s - failed setting baud rate, unsupported speed",
 						    __FUNCTION__);
-						n_baud_rate = 4800;
+						new_baudrate = priv->baud_rate;
 					}
 				} else if (priv->chiptype == CT_GENERIC) {
-					if ( (n_baud_rate = mask_to_rate(baud_mask)) == -1) {
-						err("%s - failed setting baud rate, unsupported speed (default to 4800)",
+					if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+						err("%s - failed setting baud rate, unsupported speed",
 						    __FUNCTION__);
-						n_baud_rate = 4800;
+						new_baudrate = priv->baud_rate;
 					}
 				} else {
-					info("%s - please define your chiptype, using 4800bps default", __FUNCTION__);
-					n_baud_rate = 4800;
+					info("%s - please define your chiptype", __FUNCTION__);
+					new_baudrate = priv->baud_rate;
 				}
 			} else {  /* baud rate not changing, keep the old */
-				n_baud_rate = priv->baud_rate;
+				new_baudrate = priv->baud_rate;
 			}
-			dbg("%s - baud rate is being sent as %d", __FUNCTION__, n_baud_rate);
-
+			dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate);
 			
-			/*
-			 * This algorithm accredited to Jiang Jay Zhang... thanks for all the help!
-			 */
-			for (i = 0; i < 4; ++i) {
-				feature_buffer[i] = ( n_baud_rate >> (i*8) & 0xFF );
-			}
+			memset(feature_buffer, 0, 8);
+			/* fill the feature_buffer with new configuration */
+			*((u_int32_t *)feature_buffer) = new_baudrate;
 
-			config = 0;	                 // reset config byte
-			config |= data_bits;	         // assign data bits in 2 bit space ( max 3 )
+			feature_buffer[4] |= data_bits;   /* assign data bits in 2 bit space ( max 3 ) */
 			/* 1 bit gap */
-			config |= (stop_bits << 3);      // assign stop bits in 1 bit space
-			config |= (parity_enable << 4);  // assign parity flag in 1 bit space
-			config |= (parity_type << 5); 	 // assign parity type in 1 bit space
+			feature_buffer[4] |= (stop_bits << 3);   /* assign stop bits in 1 bit space */
+			feature_buffer[4] |= (parity_enable << 4);   /* assign parity flag in 1 bit space */
+			feature_buffer[4] |= (parity_type << 5);   /* assign parity type in 1 bit space */
 			/* 1 bit gap */
-			config |= (reset << 7);		 // assign reset at end of byte, 1 bit space
-
-			feature_buffer[4] = config;
+			feature_buffer[4] |= (reset << 7);   /* assign reset at end of byte, 1 bit space */
 				
 			dbg("%s - device is being sent this feature report:", __FUNCTION__);
 			dbg("%s - %02X - %02X - %02X - %02X - %02X", __FUNCTION__, feature_buffer[0], feature_buffer[1],
 		            feature_buffer[2], feature_buffer[3], feature_buffer[4]);
 			
+			do {
 			retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
 					  	  HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
-					  	  0x0300, 0, feature_buffer, 5, 500);
+						  	  0x0300, 0, feature_buffer, 8, 500);
 
-			if (retval != 5)
+				if (tries++ >= 3)
+					break;
+
+				if (retval == EPIPE)
+					usb_clear_halt(port->serial->dev, 0x00);
+			} while (retval != 8 && retval != ENODEV);
+
+			if (retval != 8)
 				err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
 			else {
 				spin_lock_irqsave(&priv->lock, flags);
-				priv->baud_rate = n_baud_rate;
+				priv->baud_rate = new_baudrate;
 				priv->cbr_mask = baud_mask;
-				priv->current_config = config;
-				++priv->cmd_count;
+				priv->current_config = feature_buffer[4];
 				spin_unlock_irqrestore(&priv->lock, flags);
 			}
 		break;
 		case CYPRESS_GET_CONFIG:
 			dbg("%s - retreiving serial line settings", __FUNCTION__);
-			/* reset values in feature buffer */
-			memset(feature_buffer, 0, 5);
+			/* set initial values in feature buffer */
+			memset(feature_buffer, 0, 8);
 
+			do {
 			retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
 						  HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
-						  0x0300, 0, feature_buffer, 5, 500);
+							  0x0300, 0, feature_buffer, 8, 500);
+				
+				if (tries++ >= 3)
+					break;
+
+				if (retval == EPIPE)
+					usb_clear_halt(port->serial->dev, 0x00);
+			} while (retval != 5 && retval != ENODEV);
+
 			if (retval != 5) {
 				err("%s - failed to retreive serial line settings - %d", __FUNCTION__, retval);
 				return retval;
 			} else {
 				spin_lock_irqsave(&priv->lock, flags);
+
 				/* store the config in one byte, and later use bit masks to check values */
 				priv->current_config = feature_buffer[4];
-				/* reverse the process above to get the baud_mask value */
-				n_baud_rate = 0; // reset bits
-				for (i = 0; i < 4; ++i) {
-					n_baud_rate |= ( feature_buffer[i] << (i*8) );
-				}
+				priv->baud_rate = *((u_int32_t *)feature_buffer);
 				
-				priv->baud_rate = n_baud_rate;
-				if ( (priv->cbr_mask = rate_to_mask(n_baud_rate)) == 0x40)
+				if ( (priv->cbr_mask = rate_to_mask(priv->baud_rate)) == 0x40)
 					dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__);
-				++priv->cmd_count;
 				spin_unlock_irqrestore(&priv->lock, flags);
 			}
-			break;
-		default:
-			err("%s - unsupported serial control command issued", __FUNCTION__);
 	}
+	spin_lock_irqsave(&priv->lock, flags);
+	++priv->cmd_count;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	return retval;
 } /* cypress_serial_control */
 
 
-/* given a baud mask, it will return speed on success */
+/* given a baud mask, it will return integer baud on success */
 static int mask_to_rate (unsigned mask)
 {
 	int rate;
@@ -438,11 +443,12 @@
 	
 	usb_reset_configuration (serial->dev);
 	
+	interval = 1;
 	priv->cmd_ctrl = 0;
 	priv->line_control = 0;
 	priv->termios_initialized = 0;
-	priv->calledfromopen = 0;
 	priv->rx_flags = 0;
+	priv->cbr_mask = B300;
 	usb_set_serial_port_data(serial->port[0], priv);
 	
 	return (0);	
@@ -513,7 +519,6 @@
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	/* clear halts before open */
-	usb_clear_halt(serial->dev, 0x00);
 	usb_clear_halt(serial->dev, 0x81);
 	usb_clear_halt(serial->dev, 0x02);
 
@@ -531,7 +536,6 @@
 	/* raise both lines and set termios */
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->line_control = CONTROL_DTR | CONTROL_RTS;
-	priv->calledfromopen = 1;
 	priv->cmd_ctrl = 1;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	result = cypress_write(port, NULL, 0);
@@ -553,7 +557,7 @@
 	usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
 		usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
 		port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
-		cypress_read_int_callback, port, port->interrupt_in_urb->interval);
+		cypress_read_int_callback, port, interval);
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 
 	if (result){
@@ -680,12 +684,12 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	switch (port->interrupt_out_size) {
 		case 32:
-			// this is for the CY7C64013...
+			/* this is for the CY7C64013... */
 			offset = 2;
 			port->interrupt_out_buffer[0] = priv->line_control;
 			break;
 		case 8:
-			// this is for the CY7C63743...
+			/* this is for the CY7C63743... */
 			offset = 1;
 			port->interrupt_out_buffer[0] = priv->line_control;
 			break;
@@ -738,6 +742,7 @@
 
 	port->interrupt_out_urb->transfer_buffer_length = actual_size;
 	port->interrupt_out_urb->dev = port->serial->dev;
+	port->interrupt_out_urb->interval = interval;
 	result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
@@ -910,7 +915,7 @@
 	unsigned cflag, iflag, baud_mask;
 	unsigned long flags;
 	__u8 oldlines;
-	int linechange;
+	int linechange = 0;
 	
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -996,15 +1001,7 @@
 			case B115200: dbg("%s - setting baud 115200bps", __FUNCTION__); break;
 			default: dbg("%s - unknown masked baud rate", __FUNCTION__);
 		}
-		priv->line_control |= CONTROL_DTR;
-		
-		/* toggle CRTSCTS? - don't do this if being called from cypress_open */
-		if (!priv->calledfromopen) {
-			if (cflag & CRTSCTS)
-				priv->line_control |= CONTROL_RTS;
-			else
-				priv->line_control &= ~CONTROL_RTS;
-		}
+		priv->line_control = (CONTROL_DTR | CONTROL_RTS);
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 	
@@ -1014,8 +1011,6 @@
 	cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
 			       parity_type, 0, CYPRESS_SET_CONFIG);
 
-	msleep(50);			/* give some time between change and read (50ms) */
-
 	/* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
          * this should confirm that all is working if it returns what we just set */
 	cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
@@ -1031,7 +1026,6 @@
 		dbg("Using custom termios settings for a baud rate of 4800bps.");
 		/* define custom termios settings for NMEA protocol */
 
-		
 		tty->termios->c_iflag /* input modes - */
 			&= ~(IGNBRK		/* disable ignore break */
 			| BRKINT		/* disable break causes interrupt */
@@ -1052,23 +1046,16 @@
 			| ISIG			/* disable interrupt, quit, and suspend special characters */
 			| IEXTEN);		/* disable non-POSIX special characters */
 
-	} else if (priv->chiptype == CT_CYPHIDCOM) {
+	} /* CT_CYPHIDCOM: Application should handle this for device */
 
-		// Software app handling it for device...	
-
-	}
 	linechange = (priv->line_control != oldlines);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* if necessary, set lines */
-	if (!priv->calledfromopen && linechange) {
+	if (linechange) {
 		priv->cmd_ctrl = 1;
 		cypress_write(port, NULL, 0);
 	}
-
-	if (priv->calledfromopen)
-		priv->calledfromopen = 0;
-	
 } /* cypress_set_termios */
 
  
@@ -1164,7 +1151,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	switch(urb->actual_length) {
 		case 32:
-			// This is for the CY7C64013...
+			/* This is for the CY7C64013... */
 			priv->current_status = data[0] & 0xF8;
 			bytes = data[1]+2;
 			i=2;
@@ -1172,7 +1159,7 @@
 				havedata = 1;
 			break;
 		case 8:
-			// This is for the CY7C63743...
+			/* This is for the CY7C63743... */
 			priv->current_status = data[0] & 0xF8;
 			bytes = (data[0] & 0x07)+1;
 			i=1;
@@ -1245,7 +1232,7 @@
 		port->interrupt_in_urb->transfer_buffer,
 		port->interrupt_in_urb->transfer_buffer_length,
 		cypress_read_int_callback, port,
-		port->interrupt_in_urb->interval);
+		interval);
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 	if (result)
 		dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
@@ -1274,6 +1261,8 @@
 			dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
 			priv->write_urb_in_use = 0;
 			return;
+		case -EPIPE: /* no break needed */
+			usb_clear_halt(port->serial->dev, 0x02);
 		default:
 			/* error in the urb, so we have to resubmit it */
 			dbg("%s - Overflow in write", __FUNCTION__);
@@ -1535,3 +1524,5 @@
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 module_param(stats, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(stats, "Enable statistics or not");
+module_param(interval, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(interval, "Overrides interrupt interval");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 4c788c7..52394f0 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -76,7 +76,7 @@
  *      Defererence pointers after any paranoid checks, not before.
  *
  * (21/Jun/2003) Erik Nygren
- *      Added support for Home Electronics Tira-1 IR tranceiver using FT232BM chip.
+ *      Added support for Home Electronics Tira-1 IR transceiver using FT232BM chip.
  *      See <http://www.home-electro.com/tira1.htm>.  Only operates properly 
  *      at 100000 and RTS-CTS, so set custom divisor mode on startup.
  *      Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
@@ -91,7 +91,7 @@
  *      Minor whitespace and comment changes.
  *
  * (12/Jun/2003) David Norwood
- *      Added support for USB-UIRT IR tranceiver using 8U232AM chip.
+ *      Added support for USB-UIRT IR transceiver using 8U232AM chip.
  *      See <http://home.earthlink.net/~jrhees/USBUIRT/index.htm>.  Only
  *      operates properly at 312500, so set custom divisor mode on startup.
  *
@@ -272,6 +272,7 @@
 
 static struct usb_device_id id_table_sio [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
+	{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
 	{ }						/* Terminating entry */
 };
 
@@ -296,7 +297,6 @@
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -369,11 +369,14 @@
 	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) },
-	{ USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID, 0, 0x3ff) },
 	{ }						/* Terminating entry */
 };
 
@@ -382,7 +385,6 @@
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
@@ -485,11 +487,15 @@
 	{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) },
-	{ USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_RM_CANVIEW_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, EVER_ECO_PRO_CDS, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
@@ -517,7 +523,6 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
-	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
@@ -596,6 +601,22 @@
 	{ USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E808_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E809_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80A_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80B_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80C_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80D_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80E_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E80F_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E888_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E889_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88A_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88B_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88C_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88D_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
  	{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
  	{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
@@ -609,11 +630,16 @@
 	{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
 	{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
-	{ USB_DEVICE(FTDI_RM_VID, FTDI_RMCANVIEW_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
 	{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
+	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
+	{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
@@ -1457,10 +1483,10 @@
 	inter = serial->interface->altsetting->desc.bInterfaceNumber;
 
 	if (inter) {
-		priv->interface = INTERFACE_B;
+		priv->interface = PIT_SIOB;
 	}
 	else  {
-		priv->interface = INTERFACE_A;
+		priv->interface = PIT_SIOA;
 	}
 	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
 	
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index be5d60b..a52bb13 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -26,7 +26,6 @@
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
-#define FTDI_8U232AM_ALT_ALT_PID 0xf3c0 /* FTDI's second alternate PID for above */
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
@@ -137,7 +136,7 @@
 /*
  * Home Electronics (www.home-electro.com) USB gadgets
  */
-#define FTDI_HE_TIRA1_PID	0xFA78	/* Tira-1 IR tranceiver */
+#define FTDI_HE_TIRA1_PID	0xFA78	/* Tira-1 IR transceiver */
 
 /* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
 /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
@@ -157,7 +156,8 @@
  */
 #define OCT_VID			0x0B39	/* OCT vendor ID */
 /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
-/* Also rebadged as SIIG Inc. model US2308 */
+/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
+/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
 #define OCT_US101_PID		0x0421	/* OCT US101 USB to RS-232 */
 
 /* an infrared receiver for user access control with IR tags */
@@ -236,10 +236,10 @@
 
 /*
  * RM Michaelides CANview USB (http://www.rmcan.com)
- * CAN filedbus interface adapter, addad by port GmbH www.port.de)
+ * CAN fieldbus interface adapter, added by port GmbH www.port.de)
+ * Ian Abbott changed the macro names for consistency.
  */
-#define FTDI_RM_VID		0x0403	/* Vendor  Id */
-#define FTDI_RMCANVIEW_PID	0xfd60	/* Product Id */
+#define FTDI_RM_CANVIEW_PID	0xfd60	/* Product Id */
 
 /*
  * EVER Eco Pro UPS (http://www.ever.com.pl/)
@@ -247,6 +247,26 @@
 
 #define	EVER_ECO_PRO_CDS	0xe520	/* RS-232 converter */
 
+/*
+ * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
+ * USB-TTY activ, USB-TTY passiv.  Some PIDs are used by several devices
+ * and I'm not entirely sure which are used by which.
+ */
+#define FTDI_4N_GALAXY_DE_0_PID	0x8372
+#define FTDI_4N_GALAXY_DE_1_PID	0xF3C0
+#define FTDI_4N_GALAXY_DE_2_PID	0xF3C1
+
+/*
+ * Mobility Electronics products.
+ */
+#define MOBILITY_VID			0x1342
+#define MOBILITY_USB_SERIAL_PID		0x0202	/* EasiDock USB 200 serial */
+
+/*
+ * Active Robots product ids.
+ */
+#define FTDI_ACTIVE_ROBOTS_PID	0xE548	/* USB comms board */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
@@ -259,10 +279,6 @@
 #define FTDI_SIO_SET_LATENCY_TIMER	9 /* Set the latency timer */
 #define FTDI_SIO_GET_LATENCY_TIMER	10 /* Get the latency timer */
 
-/* Port interface code for FT2232C */
-#define INTERFACE_A		1
-#define INTERFACE_B		2
-
 
 /*
  *   BmRequestType:  1100 0000b
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
new file mode 100644
index 0000000..64d55fb
--- /dev/null
+++ b/drivers/usb/serial/hp4x.c
@@ -0,0 +1,85 @@
+/*
+ * HP4x Calculators Serial USB driver
+ *
+ * Copyright (C) 2005 Arthur Huillet (ahuillet@users.sf.net)
+ * Copyright (C) 2001-2005 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.00"
+#define DRIVER_DESC "HP4x (48/49) Generic Serial driver"
+
+#define HP_VENDOR_ID 0x03f0
+#define HP49GP_PRODUCT_ID 0x0121
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(HP_VENDOR_ID, HP49GP_PRODUCT_ID) },
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver hp49gp_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"HP4X",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+};
+
+static struct usb_serial_device_type hp49gp_device = {
+	.owner =		THIS_MODULE,
+	.name =			"HP4X",
+	.id_table =		id_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		NUM_DONT_CARE,
+	.num_bulk_out =		NUM_DONT_CARE,
+	.num_ports =		1,
+};
+
+static int __init hp49gp_init(void)
+{
+	int retval;
+	retval = usb_serial_register(&hp49gp_device);
+	if (retval)
+		goto failed_usb_serial_register;
+	retval = usb_register(&hp49gp_driver);
+	if (retval)
+		goto failed_usb_register;
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return 0;
+failed_usb_register:
+	usb_serial_deregister(&hp49gp_device);
+failed_usb_serial_register:
+	return retval;
+}
+
+static void __exit hp49gp_exit(void)
+{
+	usb_deregister(&hp49gp_driver);
+	usb_serial_deregister(&hp49gp_device);
+}
+
+module_init(hp49gp_init);
+module_exit(hp49gp_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index 8c1fa5e..f1804fd 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -289,7 +289,7 @@
 //
 
 //
-// Edgeport Compatiblity Descriptor
+// Edgeport Compatibility Descriptor
 //
 // This descriptor is only returned by Edgeport-compatible devices
 // supporting the EPiC spec. True ION devices do not return this
diff --git a/drivers/usb/serial/keyspan_usa90msg.h b/drivers/usb/serial/keyspan_usa90msg.h
index dd935b6..86708ec 100644
--- a/drivers/usb/serial/keyspan_usa90msg.h
+++ b/drivers/usb/serial/keyspan_usa90msg.h
@@ -19,7 +19,7 @@
 
         	This file is available under a BSD-style copyright
 
-	2. The name of InnoSys Incorprated may not be used to endorse or promote
+	2. The name of InnoSys Incorporated may not be used to endorse or promote
    	products derived from this software without specific prior written
    	permission.
 
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index d764837..5a93217 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -47,6 +47,7 @@
 #include <linux/cdrom.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
 
 #include "debug.h"
 #include "scsi.h"
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 7eff03d..f3b6028 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -786,7 +786,7 @@
 	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	// Check for media existance
+	// Check for media existence
 	rc = usbat_flash_check_media_present(uio);
 	if (rc == USBAT_FLASH_MEDIA_NONE) {
 		info->sense_key = 0x02;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index fa68dea..d2891f4 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1,5 +1,5 @@
 /* Driver for USB Mass Storage compliant devices
- * Ununsual Devices File
+ * Unusual Devices File
  *
  * $Id: unusual_devs.h,v 1.32 2002/02/25 02:41:24 mdharm Exp $
  *
@@ -48,6 +48,14 @@
  * USB development list <linux-usb-devel@lists.sourceforge.net>.
  */
 
+/* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
+ */
+UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
+                "ATMEL",
+                "SND1 Storage",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
+                US_FL_IGNORE_RESIDUE),
+
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0100,
 		"Mitsumi",
 		"USB FDD",
@@ -517,14 +525,32 @@
 		0 ),
 #endif
 
-/* Reported by Avi Kivity <avi@argo.co.il> */
-UNUSUAL_DEV( 0x05ac, 0x1203, 0x0001, 0x0001,
+/* Submitted by Sven Anderson <sven-linux@anderson.de>
+ * There are at least four ProductIDs used for iPods, so I added 0x1202 and
+ * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears
+ * to change with firmware updates, I changed the range to maximum for all
+ * iPod entries.
+ */
+UNUSUAL_DEV( 0x05ac, 0x1202, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
-UNUSUAL_DEV( 0x05ac, 0x1205, 0x0001, 0x0001,
+/* Reported by Avi Kivity <avi@argo.co.il> */
+UNUSUAL_DEV( 0x05ac, 0x1203, 0x0000, 0x9999,
+		"Apple",
+		"iPod",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
+UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
+		"Apple",
+		"iPod",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
+UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -976,6 +1002,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
 		0 ),
 
+/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
+UNUSUAL_DEV(  0x132b, 0x000b, 0x0001, 0x0001,
+		"Minolta",
+		"Dimage Z10",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
 /* Reported by Kotrla Vitezslav <kotrla@ceb.cz> */
 UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x0110,
 		"SWISSBIT",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 2a1c596..6be8fbe 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -198,6 +198,14 @@
 	  If you plan to use the LCD display with your SA-1100 system, say
 	  Y here.
 
+config FB_IMX
+	tristate "Motorola i.MX LCD support"
+	depends on FB && ARM && ARCH_IMX
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+
 config FB_CYBER2000
 	tristate "CyberPro 2000/2010/5000 support"
 	depends on FB && PCI && (BROKEN || !SPARC64)
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 92265b7..bd8dc0f 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -90,6 +90,7 @@
 obj-$(CONFIG_FB_MAXINE)		  += maxinefb.o
 obj-$(CONFIG_FB_TX3912)		  += tx3912fb.o
 obj-$(CONFIG_FB_S1D13XXX)	  += s1d13xxxfb.o
+obj-$(CONFIG_FB_IMX)              += imxfb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index acdba0c..321dbe9 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -125,28 +125,28 @@
 	case 2:
 	case 4:
 	case 8:
-		var->red.length		= 8;
+		var->red.length		= var->bits_per_pixel;
 		var->red.offset		= 0;
-		var->green.length	= 8;
+		var->green.length	= var->bits_per_pixel;
 		var->green.offset	= 0;
-		var->blue.length	= 8;
+		var->blue.length	= var->bits_per_pixel;
 		var->blue.offset	= 0;
 		break;
 	case 16:
 		var->red.length		= 5;
-		var->green.length	= 5;
+		var->green.length	= 6;
 		var->blue.length	= 5;
 		if (fb->panel->cntl & CNTL_BGR) {
-			var->red.offset		= 10;
+			var->red.offset		= 11;
 			var->green.offset	= 5;
 			var->blue.offset	= 0;
 		} else {
 			var->red.offset		= 0;
 			var->green.offset	= 5;
-			var->blue.offset	= 10;
+			var->blue.offset	= 11;
 		}
 		break;
-	case 24:
+	case 32:
 		if (fb->panel->cntl & CNTL_LCDTFT) {
 			var->red.length		= 8;
 			var->green.length	= 8;
@@ -178,6 +178,12 @@
 
 	if (fb->board->check)
 		ret = fb->board->check(fb, var);
+
+	if (ret == 0 &&
+	    var->xres_virtual * var->bits_per_pixel / 8 *
+	    var->yres_virtual > fb->fb.fix.smem_len)
+		ret = -EINVAL;
+
 	if (ret == 0)
 		ret = clcdfb_set_bitfields(fb, var);
 
@@ -250,7 +256,7 @@
 				  convert_bitfield(green, &fb->fb.var.green) |
 				  convert_bitfield(red, &fb->fb.var.red);
 
-	if (fb->fb.var.bits_per_pixel == 8 && regno < 256) {
+	if (fb->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
 		int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
 		u32 val, mask, newval;
 
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index e8eb124..ee25b9e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1057,13 +1057,14 @@
 	return radeon_screen_blank(rinfo, blank, 0);
 }
 
-static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
-                             unsigned blue, unsigned transp, struct fb_info *info)
+static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
+                             unsigned blue, unsigned transp,
+			     struct radeonfb_info *rinfo)
 {
-        struct radeonfb_info *rinfo = info->par;
 	u32 pindex;
 	unsigned int i;
-	
+
+
 	if (regno > 255)
 		return 1;
 
@@ -1078,20 +1079,7 @@
         pindex = regno;
 
         if (!rinfo->asleep) {
-        	u32 dac_cntl2, vclk_cntl = 0;
-        	
 		radeon_fifo_wait(9);
-		if (rinfo->is_mobility) {
-			vclk_cntl = INPLL(VCLK_ECP_CNTL);
-			OUTPLL(VCLK_ECP_CNTL, vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
-		}
-
-		/* Make sure we are on first palette */
-		if (rinfo->has_CRTC2) {
-			dac_cntl2 = INREG(DAC_CNTL2);
-			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
-			OUTREG(DAC_CNTL2, dac_cntl2);
-		}
 
 		if (rinfo->bpp == 16) {
 			pindex = regno * 8;
@@ -1101,24 +1089,27 @@
 			if (rinfo->depth == 15 && regno > 31)
 				return 1;
 
-			/* For 565, the green component is mixed one order below */
+			/* For 565, the green component is mixed one order
+			 * below
+			 */
 			if (rinfo->depth == 16) {
 		                OUTREG(PALETTE_INDEX, pindex>>1);
-	       	         	OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) |
-	                        	(green << 8) | (rinfo->palette[regno>>1].blue));
+	       	         	OUTREG(PALETTE_DATA,
+				       (rinfo->palette[regno>>1].red << 16) |
+	                        	(green << 8) |
+				       (rinfo->palette[regno>>1].blue));
 	                	green = rinfo->palette[regno<<1].green;
 	        	}
 		}
 
 		if (rinfo->depth != 16 || regno < 32) {
 			OUTREG(PALETTE_INDEX, pindex);
-			OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
+			OUTREG(PALETTE_DATA, (red << 16) |
+			       (green << 8) | blue);
 		}
-		if (rinfo->is_mobility)
-			OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
 	}
  	if (regno < 16) {
-		u32 *pal = info->pseudo_palette;
+		u32 *pal = rinfo->info->pseudo_palette;
         	switch (rinfo->depth) {
 		case 15:
 			pal[regno] = (regno << 10) | (regno << 5) | regno;
@@ -1138,6 +1129,84 @@
 	return 0;
 }
 
+static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+			       unsigned blue, unsigned transp,
+			       struct fb_info *info)
+{
+        struct radeonfb_info *rinfo = info->par;
+	u32 dac_cntl2, vclk_cntl = 0;
+	int rc;
+
+        if (!rinfo->asleep) {
+		if (rinfo->is_mobility) {
+			vclk_cntl = INPLL(VCLK_ECP_CNTL);
+			OUTPLL(VCLK_ECP_CNTL,
+			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
+		}
+
+		/* Make sure we are on first palette */
+		if (rinfo->has_CRTC2) {
+			dac_cntl2 = INREG(DAC_CNTL2);
+			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
+			OUTREG(DAC_CNTL2, dac_cntl2);
+		}
+	}
+
+	rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo);
+
+	if (!rinfo->asleep && rinfo->is_mobility)
+		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
+
+	return rc;
+}
+
+static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+        struct radeonfb_info *rinfo = info->par;
+	u16 *red, *green, *blue, *transp;
+	u32 dac_cntl2, vclk_cntl = 0;
+	int i, start, rc = 0;
+
+        if (!rinfo->asleep) {
+		if (rinfo->is_mobility) {
+			vclk_cntl = INPLL(VCLK_ECP_CNTL);
+			OUTPLL(VCLK_ECP_CNTL,
+			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
+		}
+
+		/* Make sure we are on first palette */
+		if (rinfo->has_CRTC2) {
+			dac_cntl2 = INREG(DAC_CNTL2);
+			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
+			OUTREG(DAC_CNTL2, dac_cntl2);
+		}
+	}
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	for (i = 0; i < cmap->len; i++) {
+		u_int hred, hgreen, hblue, htransp = 0xffff;
+
+		hred = *red++;
+		hgreen = *green++;
+		hblue = *blue++;
+		if (transp)
+			htransp = *transp++;
+		rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp,
+				       rinfo);
+		if (rc)
+			break;
+	}
+
+	if (!rinfo->asleep && rinfo->is_mobility)
+		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
+
+	return rc;
+}
 
 static void radeon_save_state (struct radeonfb_info *rinfo,
 			       struct radeon_regs *save)
@@ -1796,6 +1865,7 @@
 	.fb_check_var		= radeonfb_check_var,
 	.fb_set_par		= radeonfb_set_par,
 	.fb_setcolreg		= radeonfb_setcolreg,
+	.fb_setcmap		= radeonfb_setcmap,
 	.fb_pan_display 	= radeonfb_pan_display,
 	.fb_blank		= radeonfb_blank,
 	.fb_ioctl		= radeonfb_ioctl,
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 59e3b4b..b209adb 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -906,10 +906,13 @@
 	struct vc_data *svc = *default_mode;
 	struct display *t, *p = &fb_display[vc->vc_num];
 	int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
-	int cap = info->flags;
+	int cap;
 
 	if (info_idx == -1 || info == NULL)
 	    return;
+
+	cap = info->flags;
+
 	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
 	    (info->fix.type == FB_TYPE_TEXT))
 		logo = 0;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 7d1ae06..bcf59b2 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -337,6 +337,8 @@
 	c->vc_scan_lines = vga_scan_lines;
 	c->vc_font.height = vga_video_font_height;
 	c->vc_complement_mask = 0x7700;
+	if (vga_512_chars)
+		c->vc_hi_font_mask = 0x0800;
 	p = *c->vc_uni_pagedir_loc;
 	if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir ||
 	    !--c->vc_uni_pagedir_loc[1])
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 8b1b7c6..3894b2a 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -90,6 +90,8 @@
 	 */
 	u_char			ramdac_ctrl;
 	u_char			ramdac_powerdown;
+
+	u32			pseudo_palette[16];
 };
 
 static char *default_font = "Acorn8x8";
@@ -1223,9 +1225,7 @@
 {
 	struct cfb_info *cfb;
 
-	cfb = kmalloc(sizeof(struct cfb_info) +
-		       sizeof(u32) * 16, GFP_KERNEL);
-
+	cfb = kmalloc(sizeof(struct cfb_info), GFP_KERNEL);
 	if (!cfb)
 		return NULL;
 
@@ -1281,7 +1281,7 @@
 
 	cfb->fb.fbops		= &cyber2000fb_ops;
 	cfb->fb.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	cfb->fb.pseudo_palette	= (void *)(cfb + 1);
+	cfb->fb.pseudo_palette	= cfb->pseudo_palette;
 
 	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
 
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index c51f8fb..4e5ce8f 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -222,8 +222,11 @@
 	transp = cmap->transp;
 	start = cmap->start;
 
-	if (start < 0 || !info->fbops->fb_setcolreg)
+	if (start < 0 || (!info->fbops->fb_setcolreg &&
+			  !info->fbops->fb_setcmap))
 		return -EINVAL;
+	if (info->fbops->fb_setcmap)
+		return info->fbops->fb_setcmap(cmap, info);
 	for (i = 0; i < cmap->len; i++) {
 		hred = *red++;
 		hgreen = *green++;
@@ -250,8 +253,33 @@
 	transp = cmap->transp;
 	start = cmap->start;
 
-	if (start < 0 || !info->fbops->fb_setcolreg)
+	if (start < 0 || (!info->fbops->fb_setcolreg &&
+			  !info->fbops->fb_setcmap))
 		return -EINVAL;
+
+	/* If we can batch, do it */
+	if (info->fbops->fb_setcmap && cmap->len > 1) {
+		struct fb_cmap umap;
+		int size = cmap->len * sizeof(u16);
+		int rc;
+
+		memset(&umap, 0, sizeof(struct fb_cmap));
+		rc = fb_alloc_cmap(&umap, cmap->len, transp != NULL);
+		if (rc)
+			return rc;
+		if (copy_from_user(umap.red, red, size) ||
+		    copy_from_user(umap.green, green, size) ||
+		    copy_from_user(umap.blue, blue, size) ||
+		    (transp && copy_from_user(umap.transp, transp, size))) {
+			rc = -EFAULT;
+		}
+		umap.start = start;
+		if (rc == 0)
+			rc = info->fbops->fb_setcmap(&umap, info);
+		fb_dealloc_cmap(&umap);
+		return rc;
+	}
+
 	for (i = 0; i < cmap->len; i++, red++, blue++, green++) {
 		if (get_user(hred, red) ||
 		    get_user(hgreen, green) ||
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 25f460c..7705070 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1257,6 +1257,8 @@
 static char *video_options[FB_MAX];
 static int ofonly;
 
+extern const char *global_mode_option;
+
 /**
  * fb_get_options - get kernel boot parameters
  * @name:   framebuffer name as it would appear in
@@ -1297,9 +1299,6 @@
 	return retval;
 }
 
-
-extern const char *global_mode_option;
-
 /**
  *	video_setup - process command line options
  *	@options: string of options
@@ -1313,7 +1312,7 @@
  *	Returns zero.
  *
  */
-int __init video_setup(char *options)
+static int __init video_setup(char *options)
 {
 	int i, global = 0;
 
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 978def0..6cd1976 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -34,7 +34,6 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #endif
-#include <video/edid.h>
 #include "edid.h"
 
 /* 
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 2bdda40..c78a2c5 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -354,7 +354,7 @@
 			fb_info->var.xoffset);
 }
 
-struct class_device_attribute class_device_attrs[] = {
+static struct class_device_attribute class_device_attrs[] = {
 	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
 	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
 	__ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap),
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 9ec8781..a9a618f 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -999,8 +999,16 @@
 	info->monspecs.dclkmin = 15000000;
 
 	if (fb_validate_mode(var, info)) {
-		if (fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+		if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
+			int default_sync = (info->monspecs.hfmin-HFMIN)
+						|(info->monspecs.hfmax-HFMAX)
+						|(info->monspecs.vfmin-VFMIN)
+						|(info->monspecs.vfmax-VFMAX);
+			printk("i810fb: invalid video mode%s\n",
+			    default_sync ? "" :
+			    ". Specifying vsyncN/hsyncN parameters may help");
 			return -EINVAL;
+		}
 	}
 	
 	var->xres = xres;
@@ -2023,10 +2031,10 @@
 		 " (default = 480)");
 module_param(hsync1, int, 0);
 MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz"
-		 " (default = 31)");
+		 " (default = 29)");
 module_param(hsync2, int, 0);
 MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
-		 " (default = 31)");
+		 " (default = 30)");
 module_param(vsync1, int, 0);
 MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
 		 " (default = 50)");
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 5a72ca3..7b9bf45 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1287,12 +1287,12 @@
 		case FBIMSTT_SETCMAPREG:
 			if (copy_from_user(reg, argp, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
-			write_reg_le32(((u_int *)par->cmap_regs), reg[0], reg[1]);
+			write_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0], reg[1]);
 			return 0;
 		case FBIMSTT_GETCMAPREG:
 			if (copy_from_user(reg, argp, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
-			reg[1] = read_reg_le32(((u_int *)par->cmap_regs), reg[0]);
+			reg[1] = read_reg_le32(((u_int __iomem *)par->cmap_regs), reg[0]);
 			if (copy_to_user((void __user *)(arg + 4), &reg[1], 4))
 				return -EFAULT;
 			return 0;
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
new file mode 100644
index 0000000..8fe1c12
--- /dev/null
+++ b/drivers/video/imxfb.c
@@ -0,0 +1,695 @@
+/*
+ *  linux/drivers/video/imxfb.c
+ *
+ *  Freescale i.MX Frame Buffer device driver
+ *
+ *  Copyright (C) 2004 Sascha Hauer, Pengutronix
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Please direct your questions and comments on this driver to the following
+ * email address:
+ *
+ *	linux-arm-kernel@lists.arm.linux.org.uk
+ */
+
+//#define DEBUG 1
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <asm/arch/imxfb.h>
+
+/*
+ * Complain if VAR is out of range.
+ */
+#define DEBUG_VAR 1
+
+#include "imxfb.h"
+
+static struct imxfb_rgb def_rgb_16 = {
+	.red	= { .offset = 8,  .length = 4, },
+	.green	= { .offset = 4,  .length = 4, },
+	.blue	= { .offset = 0,  .length = 4, },
+	.transp = { .offset = 0,  .length = 0, },
+};
+
+static struct imxfb_rgb def_rgb_8 = {
+	.red	= { .offset = 0,  .length = 8, },
+	.green	= { .offset = 0,  .length = 8, },
+	.blue	= { .offset = 0,  .length = 8, },
+	.transp = { .offset = 0,  .length = 0, },
+};
+
+static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info);
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+#define LCDC_PALETTE(x) __REG2(IMX_LCDC_BASE+0x800, (x)<<2)
+static int
+imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+		       u_int trans, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	u_int val, ret = 1;
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	if (regno < fbi->palette_size) {
+		val = (CNVT_TOHW(red, 4) << 8) |
+		      (CNVT_TOHW(green,4) << 4) |
+		      CNVT_TOHW(blue,  4);
+
+		LCDC_PALETTE(regno) = val;
+		ret = 0;
+	}
+	return ret;
+}
+
+static int
+imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		   u_int trans, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	unsigned int val;
+	int ret = 1;
+
+	/*
+	 * If inverse mode was selected, invert all the colours
+	 * rather than the register number.  The register number
+	 * is what you poke into the framebuffer to produce the
+	 * colour you requested.
+	 */
+	if (fbi->cmap_inverse) {
+		red   = 0xffff - red;
+		green = 0xffff - green;
+		blue  = 0xffff - blue;
+	}
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no mater what visual we are using.
+	 */
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		ret = imxfb_setpalettereg(regno, red, green, blue, trans, info);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ *  imxfb_check_var():
+ *    Round up in the following order: bits_per_pixel, xres,
+ *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+ *    bitfields, horizontal timing, vertical timing.
+ */
+static int
+imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	int rgbidx;
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+	if (var->xres > fbi->max_xres)
+		var->xres = fbi->max_xres;
+	if (var->yres > fbi->max_yres)
+		var->yres = fbi->max_yres;
+	var->xres_virtual = max(var->xres_virtual, var->xres);
+	var->yres_virtual = max(var->yres_virtual, var->yres);
+
+	pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
+	switch (var->bits_per_pixel) {
+	case 16:
+		rgbidx = RGB_16;
+		break;
+	case 8:
+		rgbidx = RGB_8;
+		break;
+	default:
+		rgbidx = RGB_16;
+	}
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	var->red    = fbi->rgb[rgbidx]->red;
+	var->green  = fbi->rgb[rgbidx]->green;
+	var->blue   = fbi->rgb[rgbidx]->blue;
+	var->transp = fbi->rgb[rgbidx]->transp;
+
+	pr_debug("RGBT length = %d:%d:%d:%d\n",
+		var->red.length, var->green.length, var->blue.length,
+		var->transp.length);
+
+	pr_debug("RGBT offset = %d:%d:%d:%d\n",
+		var->red.offset, var->green.offset, var->blue.offset,
+		var->transp.offset);
+
+	return 0;
+}
+
+/*
+ * imxfb_set_par():
+ *	Set the user defined part of the display for the specified console
+ */
+static int imxfb_set_par(struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+
+	pr_debug("set_par\n");
+
+	if (var->bits_per_pixel == 16)
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	else if (!fbi->cmap_static)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		/*
+		 * Some people have weird ideas about wanting static
+		 * pseudocolor maps.  I suspect their user space
+		 * applications are broken.
+		 */
+		info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+	}
+
+	info->fix.line_length = var->xres_virtual *
+				  var->bits_per_pixel / 8;
+	fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
+
+	imxfb_activate_var(var, info);
+
+	return 0;
+}
+
+static void imxfb_enable_controller(struct imxfb_info *fbi)
+{
+	pr_debug("Enabling LCD controller\n");
+
+	/* initialize LCDC */
+	LCDC_RMCR &= ~RMCR_LCDC_EN;		/* just to be safe... */
+
+	LCDC_SSA	= fbi->screen_dma;
+	/* physical screen start address	    */
+	LCDC_VPW	= VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4);
+
+	LCDC_POS	= 0x00000000;   /* panning offset 0 (0 pixel offset)        */
+
+	/* disable hardware cursor */
+	LCDC_CPOS	&= ~(CPOS_CC0 | CPOS_CC1);
+
+	/* fixed burst length (see erratum 11) */
+	LCDC_DMACR = DMACR_BURST | DMACR_HM(8) | DMACR_TM(2);
+
+	LCDC_RMCR = RMCR_LCDC_EN;
+
+	if(fbi->backlight_power)
+		fbi->backlight_power(1);
+	if(fbi->lcd_power)
+		fbi->lcd_power(1);
+}
+
+static void imxfb_disable_controller(struct imxfb_info *fbi)
+{
+	pr_debug("Disabling LCD controller\n");
+
+	if(fbi->backlight_power)
+		fbi->backlight_power(0);
+	if(fbi->lcd_power)
+		fbi->lcd_power(0);
+
+	LCDC_RMCR = 0;
+}
+
+static int imxfb_blank(int blank, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+
+	pr_debug("imxfb_blank: blank=%d\n", blank);
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		imxfb_disable_controller(fbi);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		imxfb_enable_controller(fbi);
+		break;
+	}
+	return 0;
+}
+
+static struct fb_ops imxfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= imxfb_check_var,
+	.fb_set_par	= imxfb_set_par,
+	.fb_setcolreg	= imxfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_blank	= imxfb_blank,
+	.fb_cursor	= soft_cursor, /* FIXME: i.MX can do hardware cursor */
+};
+
+/*
+ * imxfb_activate_var():
+ *	Configures LCD Controller based on entries in var parameter.  Settings are
+ *	only written to the controller if changes were made.
+ */
+static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+	pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
+		var->xres, var->hsync_len,
+		var->left_margin, var->right_margin);
+	pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
+		var->yres, var->vsync_len,
+		var->upper_margin, var->lower_margin);
+
+#if DEBUG_VAR
+	if (var->xres < 16        || var->xres > 1024)
+		printk(KERN_ERR "%s: invalid xres %d\n",
+			info->fix.id, var->xres);
+	if (var->hsync_len < 1    || var->hsync_len > 64)
+		printk(KERN_ERR "%s: invalid hsync_len %d\n",
+			info->fix.id, var->hsync_len);
+	if (var->left_margin > 255)
+		printk(KERN_ERR "%s: invalid left_margin %d\n",
+			info->fix.id, var->left_margin);
+	if (var->right_margin > 255)
+		printk(KERN_ERR "%s: invalid right_margin %d\n",
+			info->fix.id, var->right_margin);
+	if (var->yres < 1 || var->yres > 511)
+		printk(KERN_ERR "%s: invalid yres %d\n",
+			info->fix.id, var->yres);
+	if (var->vsync_len > 100)
+		printk(KERN_ERR "%s: invalid vsync_len %d\n",
+			info->fix.id, var->vsync_len);
+	if (var->upper_margin > 63)
+		printk(KERN_ERR "%s: invalid upper_margin %d\n",
+			info->fix.id, var->upper_margin);
+	if (var->lower_margin > 255)
+		printk(KERN_ERR "%s: invalid lower_margin %d\n",
+			info->fix.id, var->lower_margin);
+#endif
+
+	LCDC_HCR	= HCR_H_WIDTH(var->hsync_len) |
+	                  HCR_H_WAIT_1(var->left_margin) |
+			  HCR_H_WAIT_2(var->right_margin);
+
+	LCDC_VCR	= VCR_V_WIDTH(var->vsync_len) |
+	                  VCR_V_WAIT_1(var->upper_margin) |
+			  VCR_V_WAIT_2(var->lower_margin);
+
+	LCDC_SIZE	= SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres);
+	LCDC_PCR	= fbi->pcr;
+	LCDC_PWMR	= fbi->pwmr;
+	LCDC_LSCR1	= fbi->lscr1;
+
+	return 0;
+}
+
+static void imxfb_setup_gpio(struct imxfb_info *fbi)
+{
+	int width;
+
+	LCDC_RMCR	&= ~(RMCR_LCDC_EN | RMCR_SELF_REF);
+
+	if( fbi->pcr & PCR_TFT )
+		width = 16;
+	else
+		width = 1 << ((fbi->pcr >> 28) & 0x3);
+
+	switch(width) {
+	case 16:
+		imx_gpio_mode(PD30_PF_LD15);
+		imx_gpio_mode(PD29_PF_LD14);
+		imx_gpio_mode(PD28_PF_LD13);
+		imx_gpio_mode(PD27_PF_LD12);
+		imx_gpio_mode(PD26_PF_LD11);
+		imx_gpio_mode(PD25_PF_LD10);
+		imx_gpio_mode(PD24_PF_LD9);
+		imx_gpio_mode(PD23_PF_LD8);
+	case 8:
+		imx_gpio_mode(PD22_PF_LD7);
+		imx_gpio_mode(PD21_PF_LD6);
+		imx_gpio_mode(PD20_PF_LD5);
+		imx_gpio_mode(PD19_PF_LD4);
+	case 4:
+		imx_gpio_mode(PD18_PF_LD3);
+		imx_gpio_mode(PD17_PF_LD2);
+	case 2:
+		imx_gpio_mode(PD16_PF_LD1);
+	case 1:
+		imx_gpio_mode(PD15_PF_LD0);
+	}
+
+	/* initialize GPIOs */
+	imx_gpio_mode(PD6_PF_LSCLK);
+	imx_gpio_mode(PD10_PF_SPL_SPR);
+	imx_gpio_mode(PD11_PF_CONTRAST);
+	imx_gpio_mode(PD14_PF_FLM_VSYNC);
+	imx_gpio_mode(PD13_PF_LP_HSYNC);
+	imx_gpio_mode(PD7_PF_REV);
+	imx_gpio_mode(PD8_PF_CLS);
+
+#ifndef CONFIG_MACH_PIMX1
+	/* on PiMX1 used as buffers enable signal
+	 */
+	imx_gpio_mode(PD9_PF_PS);
+#endif
+
+#ifndef CONFIG_MACH_MX1FS2
+	/* on mx1fs2 this pin is used to (de)activate the display, so we need
+	 * it as a normal gpio
+	 */
+	imx_gpio_mode(PD12_PF_ACD_OE);
+#endif
+
+}
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int imxfb_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(dev);
+	pr_debug("%s\n",__FUNCTION__);
+
+	if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
+		imxfb_disable_controller(fbi);
+	return 0;
+}
+
+static int imxfb_resume(struct device *dev, u32 level)
+{
+	struct imxfb_info *fbi = dev_get_drvdata(dev);
+	pr_debug("%s\n",__FUNCTION__);
+
+	if (level == RESUME_ENABLE)
+		imxfb_enable_controller(fbi);
+	return 0;
+}
+#else
+#define imxfb_suspend	NULL
+#define imxfb_resume	NULL
+#endif
+
+static int __init imxfb_init_fbinfo(struct device *dev)
+{
+	struct imxfb_mach_info *inf = dev->platform_data;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct imxfb_info *fbi = info->par;
+
+	pr_debug("%s\n",__FUNCTION__);
+
+	info->pseudo_palette = kmalloc( sizeof(u32) * 16, GFP_KERNEL);
+	if (!info->pseudo_palette)
+		return -ENOMEM;
+
+	memset(fbi, 0, sizeof(struct imxfb_info));
+	fbi->dev = dev;
+
+	strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
+
+	info->fix.type	= FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux		= 0;
+	info->fix.xpanstep		= 0;
+	info->fix.ypanstep		= 0;
+	info->fix.ywrapstep		= 0;
+	info->fix.accel	= FB_ACCEL_NONE;
+
+	info->var.nonstd		= 0;
+	info->var.activate		= FB_ACTIVATE_NOW;
+	info->var.height		= -1;
+	info->var.width	= -1;
+	info->var.accel_flags		= 0;
+	info->var.vmode	= FB_VMODE_NONINTERLACED;
+
+	info->fbops			= &imxfb_ops;
+	info->flags			= FBINFO_FLAG_DEFAULT;
+	info->pseudo_palette		= (fbi + 1);
+
+	fbi->rgb[RGB_16]		= &def_rgb_16;
+	fbi->rgb[RGB_8]			= &def_rgb_8;
+
+	fbi->max_xres			= inf->xres;
+	info->var.xres			= inf->xres;
+	info->var.xres_virtual		= inf->xres;
+	fbi->max_yres			= inf->yres;
+	info->var.yres			= inf->yres;
+	info->var.yres_virtual		= inf->yres;
+	fbi->max_bpp			= inf->bpp;
+	info->var.bits_per_pixel	= inf->bpp;
+	info->var.pixclock		= inf->pixclock;
+	info->var.hsync_len		= inf->hsync_len;
+	info->var.left_margin		= inf->left_margin;
+	info->var.right_margin		= inf->right_margin;
+	info->var.vsync_len		= inf->vsync_len;
+	info->var.upper_margin		= inf->upper_margin;
+	info->var.lower_margin		= inf->lower_margin;
+	info->var.sync			= inf->sync;
+	info->var.grayscale		= inf->cmap_greyscale;
+	fbi->cmap_inverse		= inf->cmap_inverse;
+	fbi->pcr			= inf->pcr;
+	fbi->lscr1			= inf->lscr1;
+	fbi->pwmr			= inf->pwmr;
+	fbi->lcd_power			= inf->lcd_power;
+	fbi->backlight_power		= inf->backlight_power;
+	info->fix.smem_len		= fbi->max_xres * fbi->max_yres *
+					  fbi->max_bpp / 8;
+
+	return 0;
+}
+
+/*
+ *      Allocates the DRAM memory for the frame buffer.  This buffer is
+ *	remapped into a non-cached, non-buffered, memory region to
+ *      allow pixel writes to occur without flushing the cache.
+ *      Once this area is remapped, all virtual memory access to the
+ *      video memory should occur at the new region.
+ */
+static int __init imxfb_map_video_memory(struct fb_info *info)
+{
+	struct imxfb_info *fbi = info->par;
+
+	fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
+	fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+					&fbi->map_dma,GFP_KERNEL);
+
+	if (fbi->map_cpu) {
+		info->screen_base = fbi->map_cpu;
+		fbi->screen_cpu = fbi->map_cpu;
+		fbi->screen_dma = fbi->map_dma;
+		info->fix.smem_start = fbi->screen_dma;
+	}
+
+	return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+static int __init imxfb_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imxfb_info *fbi;
+	struct fb_info *info;
+	struct imxfb_mach_info *inf;
+	struct resource *res;
+	int ret;
+
+	printk("i.MX Framebuffer driver\n");
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if(!res)
+		return -ENODEV;
+
+	inf = dev->platform_data;
+	if(!inf) {
+		dev_err(dev,"No platform_data available\n");
+		return -ENOMEM;
+	}
+
+	info = framebuffer_alloc(sizeof(struct imxfb_info), dev);
+	if(!info)
+		return -ENOMEM;
+
+	fbi = info->par;
+
+	dev_set_drvdata(dev, info);
+
+	ret = imxfb_init_fbinfo(dev);
+	if( ret < 0 )
+		goto failed_init;
+
+	res = request_mem_region(res->start, res->end - res->start + 1, "IMXFB");
+	if (!res) {
+		ret = -EBUSY;
+		goto failed_regs;
+	}
+
+	if (!inf->fixed_screen_cpu) {
+		ret = imxfb_map_video_memory(info);
+		if (ret) {
+			dev_err(dev, "Failed to allocate video RAM: %d\n", ret);
+			ret = -ENOMEM;
+			goto failed_map;
+		}
+	} else {
+		/* Fixed framebuffer mapping enables location of the screen in eSRAM */
+		fbi->map_cpu = inf->fixed_screen_cpu;
+		fbi->map_dma = inf->fixed_screen_dma;
+		info->screen_base = fbi->map_cpu;
+		fbi->screen_cpu = fbi->map_cpu;
+		fbi->screen_dma = fbi->map_dma;
+		info->fix.smem_start = fbi->screen_dma;
+	}
+
+	/*
+	 * This makes sure that our colour bitfield
+	 * descriptors are correctly initialised.
+	 */
+	imxfb_check_var(&info->var, info);
+
+	ret = fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0);
+	if (ret < 0)
+		goto failed_cmap;
+
+	imxfb_setup_gpio(fbi);
+
+	imxfb_set_par(info);
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(dev, "failed to register framebuffer\n");
+		goto failed_register;
+	}
+
+	imxfb_enable_controller(fbi);
+
+	return 0;
+
+failed_register:
+	fb_dealloc_cmap(&info->cmap);
+failed_cmap:
+	if (!inf->fixed_screen_cpu)
+		dma_free_writecombine(dev,fbi->map_size,fbi->map_cpu,
+		           fbi->map_dma);
+failed_map:
+	kfree(info->pseudo_palette);
+failed_regs:
+	release_mem_region(res->start, res->end - res->start);
+failed_init:
+	dev_set_drvdata(dev, NULL);
+	framebuffer_release(info);
+	return ret;
+}
+
+static int imxfb_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	/* disable LCD controller */
+	LCDC_RMCR &= ~RMCR_LCDC_EN;
+
+	unregister_framebuffer(info);
+
+	fb_dealloc_cmap(&info->cmap);
+	kfree(info->pseudo_palette);
+	framebuffer_release(info);
+
+	release_mem_region(res->start, res->end - res->start + 1);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+void  imxfb_shutdown(struct device * dev)
+{
+	/* disable LCD Controller */
+	LCDC_RMCR &= ~RMCR_LCDC_EN;
+}
+
+static struct device_driver imxfb_driver = {
+	.name		= "imx-fb",
+	.bus		= &platform_bus_type,
+	.probe		= imxfb_probe,
+	.suspend	= imxfb_suspend,
+	.resume		= imxfb_resume,
+	.remove		= imxfb_remove,
+	.shutdown	= imxfb_shutdown,
+};
+
+int __init imxfb_init(void)
+{
+	return driver_register(&imxfb_driver);
+}
+
+static void __exit imxfb_cleanup(void)
+{
+	driver_unregister(&imxfb_driver);
+}
+
+module_init(imxfb_init);
+module_exit(imxfb_cleanup);
+
+MODULE_DESCRIPTION("Motorola i.MX framebuffer driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/imxfb.h b/drivers/video/imxfb.h
new file mode 100644
index 0000000..128c3ee
--- /dev/null
+++ b/drivers/video/imxfb.h
@@ -0,0 +1,72 @@
+/*
+ * linux/drivers/video/imxfb.h
+ *
+ *  Freescale i.MX Frame Buffer device driver
+ *
+ *  Copyright (C) 2004 S.Hauer, Pengutronix
+ *
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * These are the bitfields for each
+ * display depth that we support.
+ */
+struct imxfb_rgb {
+	struct fb_bitfield	red;
+	struct fb_bitfield	green;
+	struct fb_bitfield	blue;
+	struct fb_bitfield	transp;
+};
+
+#define RGB_16	(0)
+#define RGB_8	(1)
+#define NR_RGB	2
+
+struct imxfb_info {
+	struct device		*dev;
+	struct imxfb_rgb	*rgb[NR_RGB];
+
+	u_int			max_bpp;
+	u_int			max_xres;
+	u_int			max_yres;
+
+	/*
+	 * These are the addresses we mapped
+	 * the framebuffer memory region to.
+	 */
+	dma_addr_t		map_dma;
+	u_char *		map_cpu;
+	u_int			map_size;
+
+	u_char *		screen_cpu;
+	dma_addr_t		screen_dma;
+	u_int			palette_size;
+
+	dma_addr_t		dbar1;
+	dma_addr_t		dbar2;
+
+	u_int			pcr;
+	u_int			pwmr;
+	u_int			lscr1;
+	u_int			cmap_inverse:1,
+				cmap_static:1,
+				unused:30;
+
+	void (*lcd_power)(int);
+	void (*backlight_power)(int);
+};
+
+#define IMX_NAME	"IMX"
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES	64
+#define MIN_YRES	64
+
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 6a05b70..549e229 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -135,9 +135,45 @@
 #endif
 
 #include "intelfb.h"
-#include "intelfbdrv.h"
 #include "intelfbhw.h"
 
+static void __devinit get_initial_mode(struct intelfb_info *dinfo);
+static void update_dinfo(struct intelfb_info *dinfo,
+			 struct fb_var_screeninfo *var);
+static int intelfb_get_fix(struct fb_fix_screeninfo *fix,
+			   struct fb_info *info);
+
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int intelfb_set_par(struct fb_info *info);
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info);
+
+static int intelfb_blank(int blank, struct fb_info *info);
+static int intelfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info);
+
+static void intelfb_fillrect(struct fb_info *info,
+			     const struct fb_fillrect *rect);
+static void intelfb_copyarea(struct fb_info *info,
+			     const struct fb_copyarea *region);
+static void intelfb_imageblit(struct fb_info *info,
+			      const struct fb_image *image);
+static int intelfb_cursor(struct fb_info *info,
+			   struct fb_cursor *cursor);
+
+static int intelfb_sync(struct fb_info *info);
+
+static int intelfb_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg,
+			 struct fb_info *info);
+
+static int __devinit intelfb_pci_register(struct pci_dev *pdev,
+					  const struct pci_device_id *ent);
+static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
+static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
+
 /*
  * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
  * mobile chipsets from being registered.
diff --git a/drivers/video/intelfb/intelfbdrv.h b/drivers/video/intelfb/intelfbdrv.h
deleted file mode 100644
index cc30581..0000000
--- a/drivers/video/intelfb/intelfbdrv.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef _INTELFBDRV_H
-#define _INTELFBDRV_H
-
-/*
- ******************************************************************************
- * intelfb
- *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
- * integrated graphics chips.
- *
- * Copyright © 2004 Sylvain Meyer
- *
- * Author: Sylvain Meyer
- *
- ******************************************************************************
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-static void __devinit get_initial_mode(struct intelfb_info *dinfo);
-static void update_dinfo(struct intelfb_info *dinfo,
-			 struct fb_var_screeninfo *var);
-static int intelfb_get_fix(struct fb_fix_screeninfo *fix,
-			   struct fb_info *info);
-
-static int intelfb_check_var(struct fb_var_screeninfo *var,
-			     struct fb_info *info);
-static int intelfb_set_par(struct fb_info *info);
-static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info);
-
-static int intelfb_blank(int blank, struct fb_info *info);
-static int intelfb_pan_display(struct fb_var_screeninfo *var,
-			       struct fb_info *info);
-
-static void intelfb_fillrect(struct fb_info *info,
-			     const struct fb_fillrect *rect);
-static void intelfb_copyarea(struct fb_info *info,
-			     const struct fb_copyarea *region);
-static void intelfb_imageblit(struct fb_info *info,
-			      const struct fb_image *image);
-static int intelfb_cursor(struct fb_info *info,
-			   struct fb_cursor *cursor);
-
-static int intelfb_sync(struct fb_info *info);
-
-static int intelfb_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg,
-			 struct fb_info *info);
-
-static int __devinit intelfb_pci_register(struct pci_dev *pdev,
-					  const struct pci_device_id *ent);
-static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
-static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
-
-#endif
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 849b47b..6ba10e3 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -45,7 +45,7 @@
 
 config LOGO_SUN_CLUT224
 	bool "224-color Sun Linux logo"
-	depends on LOGO && (SPARC || SPARC64)
+	depends on LOGO && (SPARC32 || SPARC64)
 	default y
 
 config LOGO_SUPERH_MONO
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 3a6555a..47733f5 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -408,6 +408,7 @@
 static int noaccel __devinitdata = 0;
 static int noscale __devinitdata = 0;
 static int paneltweak __devinitdata = 0;
+static int vram __devinitdata = 0;
 #ifdef CONFIG_MTRR
 static int nomtrr __devinitdata = 0;
 #endif
@@ -1180,7 +1181,7 @@
 
 	var->xres_virtual = (var->xres_virtual + 63) & ~63;
 
-	vramlen = info->fix.smem_len;
+	vramlen = info->screen_size;
 	pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
 	memlen = pitch * var->yres_virtual;
 
@@ -1343,7 +1344,7 @@
 	/* maximize virtual vertical length */
 	lpitch = info->var.xres_virtual *
 		((info->var.bits_per_pixel + 7) >> 3);
-	info->var.yres_virtual = info->fix.smem_len / lpitch;
+	info->var.yres_virtual = info->screen_size / lpitch;
 
 	info->pixmap.scan_align = 4;
 	info->pixmap.buf_align = 4;
@@ -1507,12 +1508,20 @@
 
 	par->FbAddress = nvidiafb_fix.smem_start;
 	par->FbMapSize = par->RamAmountKBytes * 1024;
+	if (vram && vram * 1024 * 1024 < par->FbMapSize)
+		par->FbMapSize = vram * 1024 * 1024;
+
+	/* Limit amount of vram to 64 MB */
+	if (par->FbMapSize > 64 * 1024 * 1024)
+		par->FbMapSize = 64 * 1024 * 1024;
+
 	par->FbUsableSize = par->FbMapSize - (128 * 1024);
 	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
 	    16 * 1024;
 	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
 	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
-	nvidiafb_fix.smem_len = par->FbUsableSize;
+	info->screen_size = par->FbUsableSize;
+	nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
 
 	if (!info->screen_base) {
 		printk(KERN_ERR PFX "cannot ioremap FB base\n");
@@ -1524,7 +1533,8 @@
 #ifdef CONFIG_MTRR
 	if (!nomtrr) {
 		par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
-					  par->FbMapSize, MTRR_TYPE_WRCOMB, 1);
+					  par->RamAmountKBytes * 1024,
+					  MTRR_TYPE_WRCOMB, 1);
 		if (par->mtrr.vram < 0) {
 			printk(KERN_ERR PFX "unable to setup MTRR\n");
 		} else {
@@ -1566,9 +1576,9 @@
 
       err_out_iounmap_fb:
 	iounmap(info->screen_base);
+      err_out_free_base1:
 	fb_destroy_modedb(info->monspecs.modedb);
 	nvidia_delete_i2c_busses(par);
-      err_out_free_base1:
 	iounmap(par->REGS);
       err_out_free_base0:
 	pci_release_regions(pd);
@@ -1645,6 +1655,8 @@
 			noscale = 1;
 		} else if (!strncmp(this_opt, "paneltweak:", 11)) {
 			paneltweak = simple_strtoul(this_opt+11, NULL, 0);
+		} else if (!strncmp(this_opt, "vram:", 5)) {
+			vram = simple_strtoul(this_opt+5, NULL, 0);
 #ifdef CONFIG_MTRR
 		} else if (!strncmp(this_opt, "nomtrr", 6)) {
 			nomtrr = 1;
@@ -1716,6 +1728,10 @@
 MODULE_PARM_DESC(forceCRTC,
 		 "Forces usage of a particular CRTC in case autodetection "
 		 "fails. (0 or 1) (default=autodetect)");
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram,
+		 "amount of framebuffer memory to remap in MiB"
+		 "(default=0 - remap entire memory)");
 #ifdef CONFIG_MTRR
 module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index d9a084e..c463870 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -2107,7 +2107,7 @@
 
 
 	if (rinfo->arch == RADEON_M6) {
-		for (i=0; i<8; i++)
+		for (i=0; i<7; i++)
 			OUTREG(common_regs_m6[i].reg, common_regs_m6[i].val);
 	} else {
 		for (i=0; i<9; i++)
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 5bb8d60..03d74e8 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1498,7 +1498,7 @@
 	info->fix.mmio_start = par->mmio.pbase;
 	info->fix.mmio_len   = par->mmio.len;
 
-	par->bci_base = (u32*)(par->mmio.vbase + BCI_BUFFER_OFFSET);
+	par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
 	par->bci_ptr  = 0;
 
 	savage_enable_mmio (par);
@@ -1514,7 +1514,7 @@
 	savage_disable_mmio(par);
 
 	if (par->mmio.vbase) {
-		iounmap ((void *)par->mmio.vbase);
+		iounmap(par->mmio.vbase);
 		par->mmio.vbase = NULL;
 	}
 }
@@ -1553,7 +1553,7 @@
 #endif
 
 	/* Clear framebuffer, it's all white in memory after boot */
-	memset (par->video.vbase, 0, par->video.len);
+	memset_io (par->video.vbase, 0, par->video.len);
 
 	return 0;
 }
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index 1994054..ecfd721 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -1384,7 +1384,7 @@
 /*             HELPER: SetLVDSetc            */
 /*********************************************/
 
-void
+static void
 SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    USHORT temp;
@@ -1625,7 +1625,7 @@
 /*             HELPER: GetVBType             */
 /*********************************************/
 
-void
+static void
 SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   USHORT flag=0, rev=0, nolcd=0, p4_0f, p4_25, p4_27;
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index 35030d3..7e36b7a 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -2394,11 +2394,9 @@
 void	SiS_DisplayOn(SiS_Private *SiS_Pr);
 void	SiS_DisplayOff(SiS_Private *SiS_Pr);
 void	SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-void	SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void	SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-void	SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 BOOLEAN	SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex);
 UCHAR	SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
 USHORT	SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
@@ -2444,7 +2442,6 @@
 extern void     SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 extern void 	SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
 extern void     SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void     SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 extern void     SiS_DisableBridge(SiS_Private *, PSIS_HW_INFO);
 extern BOOLEAN  SiS_SetCRT2Group(SiS_Private *, PSIS_HW_INFO, USHORT);
 extern USHORT   SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 2bc5b80..274dacd 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -86,6 +86,7 @@
 #define SiS_I2CDELAYSHORT  150
 
 static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
+static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx);
 
 /*********************************************/
 /*         HELPER: Lock/Unlock CRT2          */
@@ -100,7 +101,7 @@
       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 }
 
-void
+static void
 SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    if(HwInfo->jChipType >= SIS_315H)
@@ -4236,7 +4237,7 @@
  * from outside the context of a mode switch!
  * MUST call getVBType before calling this
  */
-void
+static void
 SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   USHORT temp=0,tempah;
@@ -9219,7 +9220,7 @@
   SiS_SetChReg(SiS_Pr, tempbx, 0);
 }
 
-void
+static void
 SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
@@ -9323,7 +9324,7 @@
 
 /* Read from Chrontel 70xx */
 /* Parameter is [Register no (S7-S0)] */
-USHORT
+static USHORT
 SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index f05aebc..f84eb54 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -293,7 +293,6 @@
 #endif
 
 void	SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void	SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void	SiS_EnableCRT2(SiS_Private *SiS_Pr);
 USHORT	SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
 void	SiS_WaitRetrace1(SiS_Private *SiS_Pr);
@@ -310,7 +309,6 @@
                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
 USHORT	SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 void	SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void	SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 BOOLEAN	SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo);
 void	SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void	SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
@@ -319,8 +317,6 @@
 USHORT 	SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
 void   	SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
 USHORT 	SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-void   	SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT 	SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempax);
 void   	SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
 #ifdef SIS315H
 static void   	SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index b773c98..6982660 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -4762,7 +4762,8 @@
 #endif
 
 
-int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit sisfb_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
 {
 	struct sisfb_chip_info 	*chipinfo = &sisfb_chip_info[ent->driver_data];
 	struct sis_video_info 	*ivideo = NULL;
@@ -5940,7 +5941,7 @@
 #endif
 #endif
 
-int __devinit sisfb_init_module(void)
+static int __devinit sisfb_init_module(void)
 {
 	sisfb_setdefaultparms();
 
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index e2fa9e1..1986a8b 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -36,6 +36,7 @@
 static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
 static int tcx_ioctl(struct inode *, struct file *, unsigned int,
 		     unsigned long, struct fb_info *);
+static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *);
 
 /*
  *  Frame buffer operations
@@ -45,6 +46,7 @@
 	.owner			= THIS_MODULE,
 	.fb_setcolreg		= tcx_setcolreg,
 	.fb_blank		= tcx_blank,
+	.fb_pan_display		= tcx_pan_display,
 	.fb_fillrect		= cfb_fillrect,
 	.fb_copyarea		= cfb_copyarea,
 	.fb_imageblit		= cfb_imageblit,
@@ -153,6 +155,12 @@
 	spin_unlock_irqrestore(&par->lock, flags);
 }
 
+static int tcx_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	tcx_reset(info);
+	return 0;
+}
+
 /**
  *      tcx_setcolreg - Optional function. Sets a color register.
  *      @regno: boolean, 0 copy local, 1 get_user() function
@@ -366,6 +374,9 @@
 	all->par.lowdepth = prom_getbool(sdev->prom_node, "tcx-8-bit");
 
 	sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+	all->info.var.red.length = 8;
+	all->info.var.green.length = 8;
+	all->info.var.blue.length = 8;
 
 	linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
 				       all->info.var.xres);
@@ -439,6 +450,7 @@
 		return;
 	}
 
+	fb_set_cmap(&all->info.cmap, &all->info);
 	tcx_init_fix(&all->info, linebytes);
 
 	if (register_framebuffer(&all->info) < 0) {
@@ -466,7 +478,7 @@
 		return -ENODEV;
 
 	for_all_sbusdev(sdev, sbus) {
-		if (!strcmp(sdev->prom_name, "tcx"))
+		if (!strcmp(sdev->prom_name, "SUNW,tcx"))
 			tcx_init_one(sdev);
 	}
 
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index c34ba39..7044226 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -317,30 +317,49 @@
 
 static u32 do_calc_pll(int freq, int* freq_out) 
 {
-	int m, n, k, best_m, best_n, best_k, f_cur, best_error;
+	int m, n, k, best_m, best_n, best_k, best_error;
 	int fref = 14318;
   
-	/* this really could be done with more intelligence --
-	   255*63*4 = 64260 iterations is silly */
 	best_error = freq;
 	best_n = best_m = best_k = 0;
-	for (n = 1; n < 256; n++) {
-		for (m = 1; m < 64; m++) {
-			for (k = 0; k < 4; k++) {
-				f_cur = fref*(n + 2)/(m + 2)/(1 << k);
-				if (abs(f_cur - freq) < best_error) {
-					best_error = abs(f_cur-freq);
-					best_n = n;
-					best_m = m;
-					best_k = k;
+
+	for (k = 3; k >= 0; k--) {
+		for (m = 63; m >= 0; m--) {
+			/*
+			 * Estimate value of n that produces target frequency
+			 * with current m and k
+			 */
+			int n_estimated = (freq * (m + 2) * (1 << k) / fref) - 2;
+
+			/* Search neighborhood of estimated n */
+			for (n = max(0, n_estimated - 1);
+					n <= min(255, n_estimated + 1); n++) {
+				/*
+				 * Calculate PLL freqency with current m, k and
+				 * estimated n
+				 */
+				int f = fref * (n + 2) / (m + 2) / (1 << k);
+				int error = abs (f - freq);
+
+				/*
+				 *  If this is the closest we've come to the
+				 * target frequency then remember n, m and k
+				 */
+				if (error  < best_error) {
+					best_error = error;
+					best_n     = n;
+					best_m     = m;
+					best_k     = k;
 				}
 			}
 		}
 	}
+
 	n = best_n;
 	m = best_m;
 	k = best_k;
 	*freq_out = fref*(n + 2)/(m + 2)/(1 << k);
+
 	return (n << 8) | (m << 2) | k;
 }
 
@@ -411,36 +430,35 @@
 
 static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) 
 {
-	u32 draminit0 = 0;
-	u32 draminit1 = 0;
-	u32 miscinit1 = 0;
-	u32 lfbsize   = 0;
-	int sgram_p   = 0;
+	u32 draminit0;
+	u32 draminit1;
+	u32 miscinit1;
+
+	int num_chips;
+	int chip_size; /* in MB */
+	u32 lfbsize;
+	int has_sgram;
 
 	draminit0 = tdfx_inl(par, DRAMINIT0);  
 	draminit1 = tdfx_inl(par, DRAMINIT1);
+
+	num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4;
  
-	if ((dev_id == PCI_DEVICE_ID_3DFX_BANSHEE) ||
-	    (dev_id == PCI_DEVICE_ID_3DFX_VOODOO3)) {             	 
-		sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1;
-  
-	lfbsize = sgram_p ?
-		(((draminit0 & DRAMINIT0_SGRAM_NUM)  ? 2 : 1) * 
-		((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) :
-		16 * 1024 * 1024;
+	if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
+		/* Banshee/Voodoo3 */
+		has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM;
+		chip_size = has_sgram ? ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 2 : 1)
+				      : 2;
 	} else {
 		/* Voodoo4/5 */
-		u32 chips, psize, banks;
+		has_sgram = 0;
+		chip_size = 1 << ((draminit0 & DRAMINIT0_SGRAM_TYPE_MASK) >> DRAMINIT0_SGRAM_TYPE_SHIFT);
+	}
+	lfbsize = num_chips * chip_size * 1024 * 1024;
 
-		chips = ((draminit0 & (1 << 26)) == 0) ? 4 : 8;
-		psize = 1 << ((draminit0 & 0x38000000) >> 28);
-		banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4;
-		lfbsize = chips * psize * banks;
-		lfbsize <<= 20;
-	}                 
-	/* disable block writes for SDRAM (why?) */
+	/* disable block writes for SDRAM */
 	miscinit1 = tdfx_inl(par, MISCINIT1);
-	miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS;
+	miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS;
 	miscinit1 |= MISCINIT1_CLUT_INV;
 
 	banshee_make_room(par, 1); 
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 3099630..9d9d200 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -45,9 +45,7 @@
 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
 
 static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
-#ifdef MODULE
 static void tgafb_pci_unregister(struct pci_dev *);
-#endif
 
 static const char *mode_option = "640x480@60";
 
@@ -1484,7 +1482,6 @@
 	return ret;
 }
 
-#ifdef MODULE
 static void __exit
 tgafb_pci_unregister(struct pci_dev *pdev)
 {
@@ -1500,6 +1497,7 @@
 	kfree(info);
 }
 
+#ifdef MODULE
 static void __exit
 tgafb_exit(void)
 {
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 8fc1278..3027841 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -19,9 +19,6 @@
 #include <linux/fb.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#ifdef __i386__
-#include <video/edid.h>
-#endif
 #include <asm/io.h>
 #include <asm/mtrr.h>
 
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 6b6bb7c..23c1251 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -131,8 +131,7 @@
 
 	vnode = AFS_FS_I(inode);
 
-	if (!PageLocked(page))
-		PAGE_BUG(page);
+	BUG_ON(!PageLocked(page));
 
 	ret = -ESTALE;
 	if (vnode->flags & AFS_VNODE_DELETED)
diff --git a/fs/aio.c b/fs/aio.c
index d06a2667..7afa222 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -40,9 +40,6 @@
 #define dprintk(x...)	do { ; } while (0)
 #endif
 
-long aio_run = 0; /* for testing only */
-long aio_wakeups = 0; /* for testing only */
-
 /*------ sysctl variables----*/
 atomic_t aio_nr = ATOMIC_INIT(0);	/* current system wide number of aio requests */
 unsigned aio_max_nr = 0x10000;	/* system wide maximum number of aio requests */
@@ -58,7 +55,7 @@
 static DECLARE_WORK(fput_work, aio_fput_routine, NULL);
 
 static DEFINE_SPINLOCK(fput_lock);
-LIST_HEAD(fput_head);
+static LIST_HEAD(fput_head);
 
 static void aio_kick_handler(void *);
 
@@ -290,7 +287,7 @@
 	spin_unlock_irq(&ctx->ctx_lock);
 }
 
-void wait_for_all_aios(struct kioctx *ctx)
+static void wait_for_all_aios(struct kioctx *ctx)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -405,7 +402,6 @@
 	req->ki_ctx = ctx;
 	req->ki_cancel = NULL;
 	req->ki_retry = NULL;
-	req->ki_obj.user = NULL;
 	req->ki_dtor = NULL;
 	req->private = NULL;
 	INIT_LIST_HEAD(&req->ki_run_list);
@@ -451,11 +447,6 @@
 {
 	if (req->ki_dtor)
 		req->ki_dtor(req);
-	req->ki_ctx = NULL;
-	req->ki_filp = NULL;
-	req->ki_obj.user = NULL;
-	req->ki_dtor = NULL;
-	req->private = NULL;
 	kmem_cache_free(kiocb_cachep, req);
 	ctx->reqs_active--;
 
@@ -592,7 +583,7 @@
  * Comments: Called with ctx->ctx_lock held. This nests
  * task_lock instead ctx_lock.
  */
-void unuse_mm(struct mm_struct *mm)
+static void unuse_mm(struct mm_struct *mm)
 {
 	struct task_struct *tsk = current;
 
@@ -623,7 +614,6 @@
 	if (list_empty(&iocb->ki_run_list)) {
 		list_add_tail(&iocb->ki_run_list,
 			&ctx->run_list);
-		iocb->ki_queued++;
 		return 1;
 	}
 	return 0;
@@ -664,10 +654,8 @@
 	}
 
 	if (!(iocb->ki_retried & 0xff)) {
-		pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n",
-			iocb->ki_retried,
-			iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
-			iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+		pr_debug("%ld retry: %d of %d\n", iocb->ki_retried,
+			iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
 	}
 
 	if (!(retry = iocb->ki_retry)) {
@@ -774,7 +762,6 @@
 static int __aio_run_iocbs(struct kioctx *ctx)
 {
 	struct kiocb *iocb;
-	int count = 0;
 	LIST_HEAD(run_list);
 
 	list_splice_init(&ctx->run_list, &run_list);
@@ -789,9 +776,7 @@
 		aio_run_iocb(iocb);
 		if (__aio_put_req(ctx, iocb))  /* drop extra ref */
 			put_ioctx(ctx);
-		count++;
  	}
-	aio_run++;
 	if (!list_empty(&ctx->run_list))
 		return 1;
 	return 0;
@@ -879,7 +864,7 @@
  * and if required activate the aio work queue to process
  * it
  */
-void queue_kicked_iocb(struct kiocb *iocb)
+static void queue_kicked_iocb(struct kiocb *iocb)
 {
  	struct kioctx	*ctx = iocb->ki_ctx;
 	unsigned long flags;
@@ -890,10 +875,8 @@
 	spin_lock_irqsave(&ctx->ctx_lock, flags);
 	run = __queue_kicked_iocb(iocb);
 	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-	if (run) {
+	if (run)
 		aio_queue_work(ctx);
-		aio_wakeups++;
-	}
 }
 
 /*
@@ -913,7 +896,6 @@
 		return;
 	}
 
-	iocb->ki_kicked++;
 	/* If its already kicked we shouldn't queue it again */
 	if (!kiocbTryKick(iocb)) {
 		queue_kicked_iocb(iocb);
@@ -984,7 +966,8 @@
 
 	tail = info->tail;
 	event = aio_ring_event(info, tail, KM_IRQ0);
-	tail = (tail + 1) % info->nr;
+	if (++tail >= info->nr)
+		tail = 0;
 
 	event->obj = (u64)(unsigned long)iocb->ki_obj.user;
 	event->data = iocb->ki_user_data;
@@ -1008,10 +991,8 @@
 
 	pr_debug("added to ring %p at [%lu]\n", iocb, tail);
 
-	pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n",
-		iocb->ki_retried,
-		iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
-		iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+	pr_debug("%ld retries: %d of %d\n", iocb->ki_retried,
+		iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
 put_rq:
 	/* everything turned out well, dispose of the aiocb. */
 	ret = __aio_put_req(ctx, iocb);
@@ -1119,7 +1100,6 @@
 	int			i = 0;
 	struct io_event		ent;
 	struct aio_timeout	to;
-	int 			event_loop = 0; /* testing only */
 	int			retry = 0;
 
 	/* needed to zero any padding within an entry (there shouldn't be 
@@ -1186,7 +1166,6 @@
 			if (to.timed_out)	/* Only check after read evt */
 				break;
 			schedule();
-			event_loop++;
 			if (signal_pending(tsk)) {
 				ret = -EINTR;
 				break;
@@ -1214,9 +1193,6 @@
 	if (timeout)
 		clear_timeout(&to);
 out:
-	pr_debug("event loop executed %d times\n", event_loop);
-	pr_debug("aio_run %ld\n", aio_run);
-	pr_debug("aio_wakeups %ld\n", aio_wakeups);
 	return i ? i : ret;
 }
 
@@ -1401,7 +1377,7 @@
  *	Performs the initial checks and aio retry method
  *	setup for the kiocb at the time of io submission.
  */
-ssize_t aio_setup_iocb(struct kiocb *kiocb)
+static ssize_t aio_setup_iocb(struct kiocb *kiocb)
 {
 	struct file *file = kiocb->ki_filp;
 	ssize_t ret = 0;
@@ -1470,7 +1446,8 @@
  * because this callback isn't used for wait queues which
  * are nested inside ioctx lock (i.e. ctx->wait)
  */
-int aio_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+static int aio_wake_function(wait_queue_t *wait, unsigned mode,
+			     int sync, void *key)
 {
 	struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
 
@@ -1514,8 +1491,7 @@
 	}
 
 	req->ki_filp = file;
-	iocb->aio_key = req->ki_key;
-	ret = put_user(iocb->aio_key, &user_iocb->aio_key);
+	ret = put_user(req->ki_key, &user_iocb->aio_key);
 	if (unlikely(ret)) {
 		dprintk("EFAULT: aio_key\n");
 		goto out_put_req;
@@ -1530,13 +1506,7 @@
 	req->ki_opcode = iocb->aio_lio_opcode;
 	init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
 	INIT_LIST_HEAD(&req->ki_wait.task_list);
-	req->ki_run_list.next = req->ki_run_list.prev = NULL;
-	req->ki_retry = NULL;
 	req->ki_retried = 0;
-	req->ki_kicked = 0;
-	req->ki_queued = 0;
-	aio_run = 0;
-	aio_wakeups = 0;
 
 	ret = aio_setup_iocb(req);
 
@@ -1544,10 +1514,14 @@
 		goto out_put_req;
 
 	spin_lock_irq(&ctx->ctx_lock);
-	list_add_tail(&req->ki_run_list, &ctx->run_list);
-	/* drain the run list */
-	while (__aio_run_iocbs(ctx))
-		;
+	if (likely(list_empty(&ctx->run_list))) {
+		aio_run_iocb(req);
+	} else {
+		list_add_tail(&req->ki_run_list, &ctx->run_list);
+		/* drain the run list */
+		while (__aio_run_iocbs(ctx))
+			;
+	}
 	spin_unlock_irq(&ctx->ctx_lock);
 	aio_put_req(req);	/* drop extra ref to req */
 	return 0;
@@ -1620,7 +1594,8 @@
  *	Finds a given iocb for cancellation.
  *	MUST be called with ctx->ctx_lock held.
  */
-struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, u32 key)
+static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
+				  u32 key)
 {
 	struct list_head *pos;
 	/* TODO: use a hash or array, this sucks. */
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index f5a52c8..c7b2b88 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -84,6 +84,7 @@
 	char *name;
 	/* This is for status reporting upon return */
 	int status;
+	atomic_t notified;
 	atomic_t wait_ctr;
 };
 
@@ -101,6 +102,7 @@
 	int needs_reghost;
 	struct super_block *sb;
 	struct semaphore wq_sem;
+	spinlock_t fs_lock;
 	struct autofs_wait_queue *queues; /* Wait queue pointer */
 };
 
@@ -126,9 +128,18 @@
 static inline int autofs4_ispending(struct dentry *dentry)
 {
 	struct autofs_info *inf = autofs4_dentry_ino(dentry);
+	int pending = 0;
 
-	return (dentry->d_flags & DCACHE_AUTOFS_PENDING) ||
-		(inf != NULL && inf->flags & AUTOFS_INF_EXPIRING);
+	if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
+		return 1;
+
+	if (inf) {
+		spin_lock(&inf->sbi->fs_lock);
+		pending = inf->flags & AUTOFS_INF_EXPIRING;
+		spin_unlock(&inf->sbi->fs_lock);
+	}
+
+	return pending;
 }
 
 static inline void autofs4_copy_atime(struct file *src, struct file *dst)
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 31540a6..500425e 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -99,6 +99,10 @@
 	if (!autofs4_can_expire(top, timeout, do_now))
 		return 0;
 
+	/* Is someone visiting anywhere in the tree ? */
+	if (may_umount_tree(mnt))
+		return 0;
+
 	spin_lock(&dcache_lock);
 repeat:
 	next = this_parent->d_subdirs.next;
@@ -270,10 +274,18 @@
 
 		/* Case 2: tree mount, expire iff entire tree is not busy */
 		if (!exp_leaves) {
+			/* Lock the tree as we must expire as a whole */
+			spin_lock(&sbi->fs_lock);
 			if (autofs4_check_tree(mnt, dentry, timeout, do_now)) {
-			expired = dentry;
-			break;
+				struct autofs_info *inf = autofs4_dentry_ino(dentry);
+
+				/* Set this flag early to catch sys_chdir and the like */
+				inf->flags |= AUTOFS_INF_EXPIRING;
+				spin_unlock(&sbi->fs_lock);
+				expired = dentry;
+				break;
 			}
+			spin_unlock(&sbi->fs_lock);
 		/* Case 3: direct mount, expire individual leaves */
 		} else {
 			expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index a525607..4bb14cc 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -206,6 +206,7 @@
 	sbi->version = 0;
 	sbi->sub_version = 0;
 	init_MUTEX(&sbi->wq_sem);
+	spin_lock_init(&sbi->fs_lock);
 	sbi->queues = NULL;
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 1ab24a6..5a40d36 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -210,17 +210,8 @@
 		wq->len = len;
 		wq->status = -EINTR; /* Status return if interrupted */
 		atomic_set(&wq->wait_ctr, 2);
+		atomic_set(&wq->notified, 1);
 		up(&sbi->wq_sem);
-
-		DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d",
-			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
-		/* autofs4_notify_daemon() may block */
-		if (notify != NFY_NONE) {
-			autofs4_notify_daemon(sbi,wq, 
-					notify == NFY_MOUNT ?
-						  autofs_ptype_missing :
-						  autofs_ptype_expire_multi);
-		}
 	} else {
 		atomic_inc(&wq->wait_ctr);
 		up(&sbi->wq_sem);
@@ -229,6 +220,17 @@
 			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
 	}
 
+	if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) {
+		int type = (notify == NFY_MOUNT ?
+			autofs_ptype_missing : autofs_ptype_expire_multi);
+
+		DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
+			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify));
+
+		/* autofs4_notify_daemon() may block */
+		autofs4_notify_daemon(sbi, wq, type);
+	}
+
 	/* wq->name is NULL if and only if the lock is already released */
 
 	if ( sbi->catatonic ) {
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 672a319..e172180 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -47,7 +47,7 @@
 	.get_unmapped_area = EIO_ERROR,
 };
 
-struct inode_operations bad_inode_ops =
+static struct inode_operations bad_inode_ops =
 {
 	.create		= EIO_ERROR,
 	.lookup		= EIO_ERROR,
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 6ae62cb..ce9423b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -945,7 +945,7 @@
 	retval = arch_setup_additional_pages(bprm, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
-		goto out_free_dentry;
+		goto out;
 	}
 #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
 
diff --git a/fs/bio.c b/fs/bio.c
index e5349e8..3a1472a 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -140,6 +140,7 @@
  * bio_alloc_bioset - allocate a bio for I/O
  * @gfp_mask:   the GFP_ mask given to the slab allocator
  * @nr_iovecs:	number of iovecs to pre-allocate
+ * @bs:		the bio_set to allocate from
  *
  * Description:
  *   bio_alloc_bioset will first try it's on mempool to satisfy the allocation.
@@ -629,6 +630,7 @@
 
 /**
  *	bio_map_user	-	map user address into bio
+ *	@q: the request_queue_t for the bio
  *	@bdev: destination block device
  *	@uaddr: start of user address
  *	@len: length in bytes
diff --git a/fs/block_dev.c b/fs/block_dev.c
index d19d07c..c0cbd1b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -530,7 +530,7 @@
 	if (!bdops->media_changed(bdev->bd_disk))
 		return 0;
 
-	if (__invalidate_device(bdev, 0))
+	if (__invalidate_device(bdev))
 		printk("VFS: busy inodes on changed media.\n");
 
 	if (bdops->revalidate_disk)
diff --git a/fs/buffer.c b/fs/buffer.c
index 3b12cf9..6f88dcc 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -218,7 +218,7 @@
 	sb = get_super(bdev);
 	if (sb && !(sb->s_flags & MS_RDONLY)) {
 		sb->s_frozen = SB_FREEZE_WRITE;
-		wmb();
+		smp_wmb();
 
 		sync_inodes_sb(sb, 0);
 		DQUOT_SYNC(sb);
@@ -235,7 +235,7 @@
 		sync_inodes_sb(sb, 1);
 
 		sb->s_frozen = SB_FREEZE_TRANS;
-		wmb();
+		smp_wmb();
 
 		sync_blockdev(sb->s_bdev);
 
@@ -263,7 +263,7 @@
 		if (sb->s_op->unlockfs)
 			sb->s_op->unlockfs(sb);
 		sb->s_frozen = SB_UNFROZEN;
-		wmb();
+		smp_wmb();
 		wake_up(&sb->s_wait_unfrozen);
 		drop_super(sb);
 	}
@@ -774,15 +774,14 @@
 /**
  * sync_mapping_buffers - write out and wait upon a mapping's "associated"
  *                        buffers
- * @buffer_mapping - the mapping which backs the buffers' data
- * @mapping - the mapping which wants those buffers written
+ * @mapping: the mapping which wants those buffers written
  *
  * Starts I/O against the buffers at mapping->private_list, and waits upon
  * that I/O.
  *
- * Basically, this is a convenience function for fsync().  @buffer_mapping is
- * the blockdev which "owns" the buffers and @mapping is a file or directory
- * which needs those buffers to be written for a successful fsync().
+ * Basically, this is a convenience function for fsync().
+ * @mapping is a file or directory which needs those buffers to be written for
+ * a successful fsync().
  */
 int sync_mapping_buffers(struct address_space *mapping)
 {
@@ -1211,7 +1210,7 @@
 	return 1;
 }
 
-struct buffer_head *
+static struct buffer_head *
 __getblk_slow(struct block_device *bdev, sector_t block, int size)
 {
 	/* Size must be multiple of hard sectorsize */
@@ -1263,6 +1262,7 @@
 
 /**
  * mark_buffer_dirty - mark a buffer_head as needing writeout
+ * @bh: the buffer_head to mark dirty
  *
  * mark_buffer_dirty() will set the dirty bit against the buffer, then set its
  * backing page dirty, then tag the page as dirty in its address_space's radix
@@ -1501,6 +1501,7 @@
 
 /**
  *  __bread() - reads a specified block and returns the bh
+ *  @bdev: the block_device to read from
  *  @block: number of block
  *  @size: size (in bytes) to read
  * 
@@ -1808,7 +1809,6 @@
 	} while (bh != head);
 
 	do {
-		get_bh(bh);
 		if (!buffer_mapped(bh))
 			continue;
 		/*
@@ -1837,7 +1837,6 @@
 	 */
 	BUG_ON(PageWriteback(page));
 	set_page_writeback(page);
-	unlock_page(page);
 
 	do {
 		struct buffer_head *next = bh->b_this_page;
@@ -1845,9 +1844,9 @@
 			submit_bh(WRITE, bh);
 			nr_underway++;
 		}
-		put_bh(bh);
 		bh = next;
 	} while (bh != head);
+	unlock_page(page);
 
 	err = 0;
 done:
@@ -1886,7 +1885,6 @@
 	bh = head;
 	/* Recovery: lock and submit the mapped buffers */
 	do {
-		get_bh(bh);
 		if (buffer_mapped(bh) && buffer_dirty(bh)) {
 			lock_buffer(bh);
 			mark_buffer_async_write(bh);
@@ -1909,7 +1907,6 @@
 			submit_bh(WRITE, bh);
 			nr_underway++;
 		}
-		put_bh(bh);
 		bh = next;
 	} while (bh != head);
 	goto done;
@@ -1952,7 +1949,7 @@
 		if (!buffer_mapped(bh)) {
 			err = get_block(inode, block, bh, 1);
 			if (err)
-				goto out;
+				break;
 			if (buffer_new(bh)) {
 				clear_buffer_new(bh);
 				unmap_underlying_metadata(bh->b_bdev,
@@ -1994,10 +1991,12 @@
 	while(wait_bh > wait) {
 		wait_on_buffer(*--wait_bh);
 		if (!buffer_uptodate(*wait_bh))
-			return -EIO;
+			err = -EIO;
 	}
-	return 0;
-out:
+	if (!err)
+		return err;
+
+	/* Error case: */
 	/*
 	 * Zero out any newly allocated blocks to avoid exposing stale
 	 * data.  If BH_New is set, we know that the block was newly
@@ -2078,8 +2077,7 @@
 	int nr, i;
 	int fully_mapped = 1;
 
-	if (!PageLocked(page))
-		PAGE_BUG(page);
+	BUG_ON(!PageLocked(page));
 	blocksize = 1 << inode->i_blkbits;
 	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize, 0);
@@ -2917,7 +2915,7 @@
 
 	bh = head;
 	do {
-		if (buffer_write_io_error(bh))
+		if (buffer_write_io_error(bh) && page->mapping)
 			set_bit(AS_EIO, &page->mapping->flags);
 		if (buffer_busy(bh))
 			goto failed;
@@ -3115,7 +3113,7 @@
 
 	bh_cachep = kmem_cache_create("buffer_head",
 			sizeof(struct buffer_head), 0,
-			SLAB_PANIC, init_buffer_head, NULL);
+			SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_buffer_head, NULL);
 
 	/*
 	 * Limit the bh occupancy to 10% of ZONE_NORMAL
diff --git a/fs/char_dev.c b/fs/char_dev.c
index a745b1d..c1e3537 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -328,7 +328,7 @@
 	spin_unlock(&cdev_lock);
 }
 
-void cdev_purge(struct cdev *cdev)
+static void cdev_purge(struct cdev *cdev)
 {
 	spin_lock(&cdev_lock);
 	while (!list_empty(&cdev->list)) {
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index acce36e..72fdc10 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -4,13 +4,16 @@
 
 The author wishes to express his appreciation and thanks to:
 Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
-improvements. Thanks to IBM for allowing me the time and test resources to pursue
-this project. Jim McDonough from IBM (and the Samba Team) for his help.
-The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
+improvements. Thanks to IBM for allowing me time and test resources to pursue
+this project, to Jim McDonough from IBM (and the Samba Team) for his help, to
+the IBM Linux JFS team for explaining many esoteric Linux filesystem features.
+Jeremy Allison of the Samba team has done invaluable work in adding the server
+side of the original CIFS Unix extensions and reviewing and implementing
+portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank
 Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
-for proving years ago that a very good smb/cifs client could be done on a Unix like 
-operating system.  Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin 
-and others for their work on the Linux smbfs module over the years. Thanks to
+for proving years ago that very good smb/cifs clients could be done on Unix-like
+operating systems.  Volker Lendecke, Andrew Tridgell, Urban Widmark, John 
+Newbigin and others for their work on the Linux smbfs module.  Thanks to
 the other members of the Storage Network Industry Association CIFS Technical
 Workgroup for their work specifying this highly complex protocol and finally
 thanks to the Samba team for their technical advice and encouragement.
@@ -24,9 +27,11 @@
 Sergey Vlasov
 Richard Hughes
 Yury Umanets
-Mark Hamzy
+Mark Hamzy (for some of the early cifs IPv6 work)
 Domen Puncer
-Jesper Juhl
+Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
+Vince Negri and Dave Stahl (for finding an important caching bug)
+Adrian Bunk (kcalloc cleanups)
 
 Test case and Bug Report contributors
 -------------------------------------
@@ -36,7 +41,8 @@
 Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
 Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
 mention to the Stanford Checker (SWAT) which pointed out many minor
-bugs in error paths.
+bugs in error paths.  Valuable suggestions also have come from Al Viro
+and Dave Miller.
 
 And thanks to the IBM LTC and Power test teams and SuSE testers for
 finding multiple bugs during excellent stress test runs.
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 5316c8d..95483ba 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,44 @@
-Version 1.31
+Version 1.34
+------------
+Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
+Do not oops if root user kills cifs oplock kernel thread or
+kills the cifsd thread (NB: killing the cifs kernel threads is not
+recommended, unmount and rmmod cifs will kill them when they are
+no longer needed).  Fix readdir to ASCII servers (ie older servers
+which do not support Unicode) and also require asterik.
+
+
+Version 1.33
+------------
+Fix caching problem, in which readdir of directory containing a file
+which was cached could cause the file's time stamp to be updated
+without invalidating the readahead data (so we could get stale
+file data on the client for that file even as the server copy changed).
+Cleanup response processing so cifsd can not loop when abnormally
+terminated.
+
+
+Version 1.32
 ------------
 Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
 transact response for an SMB request and search entry split across two frames.
+Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server)
+as new protocol extensions. Do not send Get/Set calls for POSIX ACLs
+unless server explicitly claims to support them in CIFS Unix extensions
+POSIX ACL capability bit. Fix packet signing when multiuser mounting with
+different users from the same client to the same server. Fix oops in
+cifs_close. Add mount option for remapping reserved characters in
+filenames (also allow recognizing files with created by SFU which have any
+of these seven reserved characters, except backslash, to be recognized).
+Fix invalid transact2 message (we were sometimes trying to interpret
+oplock breaks as SMB responses). Add ioctl for checking that the
+current uid matches the uid of the mounter (needed by umount.cifs).
+Reduce the number of large buffer allocations in cifs response processing
+(significantly reduces memory pressure under heavy stress with multiple
+processes accessing the same server at the same time).
+
+Version 1.31
+------------
 Fix updates of DOS attributes and time fields so that files on NT4 servers
 do not get marked delete on close. Display sizes of cifs buffer pools in
 cifs stats. Fix oops in unmount when cifsd thread being killed by 
diff --git a/fs/cifs/README b/fs/cifs/README
index 0f20edc..e74df0c 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -32,9 +32,9 @@
 6) make modules (or "make" if CIFS VFS not to be built as a module)
 
 For Linux 2.6:
-1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
-at bk://linux.bkbits.net/linux-2.5) and change directory into the top
-of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
+1) Download the kernel (e.g. from http://www.kernel.org)
+and change directory into the top of the kernel directory tree
+(e.g. /usr/src/linux-2.5.73)
 2) make menuconfig (or make xconfig)
 3) select cifs from within the network filesystem choices
 4) save and exit
@@ -75,7 +75,7 @@
 ====================
 To permit users to mount and unmount over directories they own is possible
 with the cifs vfs.  A way to enable such mounting is to mark the mount.cifs
-utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to 
+utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to 
 umount shares they mount requires
 1) mount.cifs version 1.4 or later
 2) an entry for the share in /etc/fstab indicating that a user may
@@ -97,6 +97,26 @@
 There is a corresponding manual page for cifs mounting in the Samba 3.0 and
 later source tree in docs/manpages/mount.cifs.8 
 
+Allowing User Unmounts
+======================
+To permit users to ummount directories that they have user mounted (see above),
+the utility umount.cifs may be used.  It may be invoked directly, or if 
+umount.cifs is placed in /sbin, umount can invoke the cifs umount helper
+(at least for most versions of the umount utility) for umount of cifs
+mounts, unless umount is invoked with -i (which will avoid invoking a umount
+helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked
+as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions
+allow adding entries to a file to the /etc/permissions file to achieve the
+equivalent suid effect).  For this utility to succeed the target path
+must be a cifs mount, and the uid of the current user must match the uid
+of the user who mounted the resource.
+
+Also note that the customary way of allowing user mounts and unmounts is 
+(instead of using mount.cifs and unmount.cifs as suid) to add a line
+to the file /etc/fstab for each //server/share you wish to mount, but
+this can become unwieldy when potential mount targets include many
+or  unpredictable UNC names.
+
 Samba Considerations 
 ==================== 
 To get the maximum benefit from the CIFS VFS, we recommend using a server that 
@@ -376,6 +396,19 @@
 		attributes) to the server (default) e.g. via setfattr 
 		and getfattr utilities. 
   nouser_xattr  Do not allow getfattr/setfattr to get/set xattrs 
+  mapchars      Translate six of the seven reserved characters (not backslash)
+			*?<>|:
+		to the remap range (above 0xF000), which also
+		allows the CIFS client to recognize files created with
+		such characters by Windows's POSIX emulation. This can
+		also be useful when mounting to most versions of Samba
+		(which also forbids creating and opening files
+		whose names contain any of these seven characters).
+		This has no effect if the server does not support
+		Unicode on the wire.
+ nomapchars     Do not translate any of these seven characters (default).
+ remount        remount the share (often used to change from ro to rw mounts
+	        or vice versa)
 		
 The mount.cifs mount helper also accepts a few mount options before -o
 including:
@@ -392,7 +425,7 @@
 =======================================
 Informational pseudo-files:
 DebugData		Displays information about active CIFS sessions
-			and shares.
+			and shares, as well as the cifs.ko version.
 Stats			Lists summary resource usage information as well as per
 			share statistics, if CONFIG_CIFS_STATS in enabled
 			in the kernel configuration.
@@ -449,7 +482,7 @@
 Two other experimental features are under development and to test 
 require enabling CONFIG_CIFS_EXPERIMENTAL
 
-	More efficient write operations and SMB buffer handling
+	More efficient write operations
 
 	DNOTIFY fcntl: needed for support of directory change 
 			    notification and perhaps later for file leases)
@@ -467,8 +500,8 @@
 	
 Also note that "cat /proc/fs/cifs/DebugData" will display information about 
 the active sessions and the shares that are mounted.  Note: NTLMv2 enablement 
-will not work since they its implementation is not quite complete yet.
-Do not alter these configuration values unless you are doing specific testing.  
+will not work since its implementation is not quite complete yet. Do not alter
+the ExtendedSecurity configuration value unless you are doing specific testing.
 Enabling extended security works to Windows 2000 Workstations and XP but not to 
 Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" 
 (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not 
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index f4e3e1f..8cc8816 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
-version 1.22 July 30, 2004 
+version 1.34 April 29, 2005
 
 A Partial List of Missing Features
 ==================================
@@ -14,7 +14,7 @@
 better)
 
 c) multi-user mounts - multiplexed sessionsetups over single vc
-(ie tcp session) - prettying up needed, and more testing needed
+(ie tcp session) - more testing needed
 
 d) Kerberos/SPNEGO session setup support - (started)
 
@@ -67,12 +67,26 @@
 
 r) Implement O_DIRECT flag on open (already supported on mount)
 
-KNOWN BUGS (updated December 10, 2004)
+s) Allow remapping of last remaining character (\) to +0xF000 which
+(this character is valid for POSIX but not for Windows)
+
+t) Create UID mapping facility so server UIDs can be mapped on a per
+mount or a per server basis to client UIDs or nobody if no mapping
+exists.  This is helpful when Unix extensions are negotiated to
+allow better permission checking when UIDs differ on the server
+and client.  Add new protocol request to the CIFS protocol 
+standard for asking the server for the corresponding name of a
+particular uid.
+
+KNOWN BUGS (updated April 29, 2005)
 ====================================
+See http://bugzilla.samba.org - search on product "CifsVFS" for
+current bug list.
+
 1) existing symbolic links (Windows reparse points) are recognized but
 can not be created remotely. They are implemented for Samba and those that
-support the CIFS Unix extensions but Samba has a bug currently handling
-symlink text beginning with slash
+support the CIFS Unix extensions, although earlier versions of Samba
+overly restrict the pathnames.
 2) follow_link and readdir code does not follow dfs junctions
 but recognizes them
 3) create of new files to FAT partitions on Windows servers can
@@ -98,7 +112,5 @@
 and when signing is disabled to request larger read sizes (larger than 
 negotiated size) and send larger write sizes to modern servers.
 
-4) More exhaustively test the recently added NT4 support against various
-NT4 service pack levels, and fix cifs_setattr for setting file times and 
-size to fall back to level 1 when error invalid level returned.
-
+4) More exhaustively test against less common servers.  More testing
+against Windows 9x, Windows ME servers.
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index db28b56..4061e43 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs_debug.c
  *
- *   Copyright (C) International Business Machines  Corp., 2000,2003
+ *   Copyright (C) International Business Machines  Corp., 2000,2005
  *
  *   Modified by Steve French (sfrench@us.ibm.com)
  *
@@ -29,6 +29,7 @@
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifs_debug.h"
+#include "cifsfs.h"
 
 void
 cifs_dump_mem(char *label, void *data, int length)
@@ -78,8 +79,9 @@
 		    "Display Internal CIFS Data Structures for Debugging\n"
 		    "---------------------------------------------------\n");
 	buf += length;
-
-	length = sprintf(buf, "Servers:\n");
+	length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
+	buf += length;
+	length = sprintf(buf, "Servers:");
 	buf += length;
 
 	i = 0;
@@ -87,12 +89,21 @@
 	list_for_each(tmp, &GlobalSMBSessionList) {
 		i++;
 		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
-		length =
-		    sprintf(buf,
-			    "\n%d) Name: %s  Domain: %s Mounts: %d ServerOS: %s  \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
-				i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
-				ses->serverOS, ses->serverNOS, ses->capabilities,ses->status);
-		buf += length;
+		if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
+		   (ses->serverNOS == NULL)) {
+			buf += sprintf("\nentry for %s not fully displayed\n\t",
+					ses->serverName);
+			
+		} else {
+			length =
+			    sprintf(buf,
+				    "\n%d) Name: %s  Domain: %s Mounts: %d ServerOS: %s  \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
+				i, ses->serverName, ses->serverDomain,
+				atomic_read(&ses->inUse),
+				ses->serverOS, ses->serverNOS,
+				ses->capabilities,ses->status);
+			buf += length;
+		}
 		if(ses->server) {
 			buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
 				ses->server->tcpStatus,
@@ -100,7 +111,7 @@
 				ses->server->secMode,
 				atomic_read(&ses->server->inFlight));
 			
-			length = sprintf(buf, "\nMIDs: \n");
+			length = sprintf(buf, "\nMIDs:\n");
 			buf += length;
 
 			spin_lock(&GlobalMid_Lock);
@@ -109,7 +120,12 @@
 					mid_q_entry,
 					qhead);
 				if(mid_entry) {
-					length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
+					length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
+						mid_entry->midState,
+						(int)mid_entry->command,
+						mid_entry->pid,
+						mid_entry->tsk,
+						mid_entry->mid);
 					buf += length;
 				}
 			}
@@ -121,7 +137,7 @@
 	sprintf(buf, "\n");
 	buf++;
 
-	length = sprintf(buf, "\nShares:\n");
+	length = sprintf(buf, "Shares:");
 	buf += length;
 
 	i = 0;
@@ -200,7 +216,8 @@
 	buf += item_length;      
 	item_length = 
 		sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
-			bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter);
+			bufAllocCount.counter,
+			cifs_min_rcv + tcpSesAllocCount.counter);
 	length += item_length;
 	buf += item_length;
 	item_length = 
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 77da902..ec00d61 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -23,6 +23,7 @@
 #define CIFS_MOUNT_SERVER_INUM  4 /* inode numbers from uniqueid from server */
 #define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
 #define CIFS_MOUNT_NO_XATTR  0x10 /* if set - disable xattr support */
+#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index a17adf4..99a096d 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -76,8 +76,8 @@
 				charlen));
 			to[i] = cpu_to_le16(0x003f);	/* a question mark */
 			charlen = 1;
-		}
-		to[i] = cpu_to_le16(to[i]);
+		} else 
+			to[i] = cpu_to_le16(to[i]);
 
 	}
 
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 78829e7..1959c7c 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -50,7 +50,7 @@
 	return 0;
 }
 
-int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
 	__u32 * pexpected_response_sequence_number)
 {
 	int rc = 0;
@@ -59,21 +59,21 @@
 	/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
 	/* BB remember to add code to save expected sequence number in midQ entry BB */
 
-	if((cifs_pdu == NULL) || (ses == NULL))
+	if((cifs_pdu == NULL) || (server == NULL))
 		return -EINVAL;
 
 	if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 
 		return rc;
 
 	spin_lock(&GlobalMid_Lock);
-	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
+	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 	
-	*pexpected_response_sequence_number = ses->sequence_number++;
-	ses->sequence_number++;
+	*pexpected_response_sequence_number = server->sequence_number++;
+	server->sequence_number++;
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
+	rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
 	if(rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
 	else
@@ -190,7 +190,7 @@
 	hmac_md5_update((const unsigned char *) unicode_buf,
 		(user_name_len+dom_name_len)*2,&ctx);
 
-	hmac_md5_final(ses->mac_signing_key,&ctx);
+	hmac_md5_final(ses->server->mac_signing_key,&ctx);
 	kfree(ucase_buf);
 	kfree(unicode_buf);
 	return 0;
@@ -200,7 +200,7 @@
 	struct HMACMD5Context context;
 	memcpy(v2_session_response + 8, ses->server->cryptKey,8);
 	/* gen_blob(v2_session_response + 16); */
-	hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
+	hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
 
 	hmac_md5_update(ses->server->cryptKey,8,&context);
 /*	hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 5082fce..8cc23e7 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -169,7 +169,8 @@
 static int
 cifs_statfs(struct super_block *sb, struct kstatfs *buf)
 {
-	int xid, rc = -EOPNOTSUPP;
+	int xid; 
+	int rc = -EOPNOTSUPP;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 
@@ -181,31 +182,34 @@
 	buf->f_type = CIFS_MAGIC_NUMBER;
 
 	/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
-	buf->f_namelen = PATH_MAX;	/* PATH_MAX may be too long - it would presumably
-					   be length of total path, note that some servers may be 
-					   able to support more than this, but best to be safe
-					   since Win2k and others can not handle very long filenames */
+	buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would 
+				      presumably be total path, but note
+				      that some servers (includinng Samba 3)
+				      have a shorter maximum path */
 	buf->f_files = 0;	/* undefined */
 	buf->f_ffree = 0;	/* unlimited */
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 /* BB we could add a second check for a QFS Unix capability bit */
-    if (pTcon->ses->capabilities & CAP_UNIX)
-	    rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls);
+/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
+    if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
+			le64_to_cpu(pTcon->fsUnixInfo.Capability)))
+	    rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf);
 
     /* Only need to call the old QFSInfo if failed
     on newer one */
     if(rc)
 #endif /* CIFS_EXPERIMENTAL */
-	rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
+	rc = CIFSSMBQFSInfo(xid, pTcon, buf);
 
 	/*     
 	   int f_type;
 	   __fsid_t f_fsid;
 	   int f_namelen;  */
-	/* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
+	/* BB get from info in tcon struct at mount time call to QFSAttrInfo */
 	FreeXid(xid);
-	return 0;		/* always return success? what if volume is no longer available? */
+	return 0;		/* always return success? what if volume is no
+				   longer available? */
 }
 
 static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
@@ -559,6 +563,10 @@
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
 	.sendfile = generic_file_sendfile,
+#ifdef CONFIG_CIFS_POSIX
+	.ioctl	= cifs_ioctl,
+#endif /* CONFIG_CIFS_POSIX */
+
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	.readv = generic_file_readv,
 	.writev = generic_file_writev,
@@ -579,6 +587,10 @@
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
 	.sendfile = generic_file_sendfile, /* BB removeme BB */
+#ifdef CONFIG_CIFS_POSIX
+	.ioctl  = cifs_ioctl,
+#endif /* CONFIG_CIFS_POSIX */
+
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	.dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -591,6 +603,7 @@
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 	.dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
+        .ioctl  = cifs_ioctl,
 };
 
 static void
@@ -822,6 +835,7 @@
 		}
 	} while(!signal_pending(current));
 	complete_and_exit (&cifs_oplock_exited, 0);
+	oplockThread = NULL;
 }
 
 static int __init
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 451f18a..d00b3bf 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsfs.h
  *
- *   Copyright (c) International Business Machines  Corp., 2002
+ *   Copyright (c) International Business Machines  Corp., 2002, 2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -91,8 +91,10 @@
 			const char *symname);
 extern int	cifs_removexattr(struct dentry *, const char *);
 extern int 	cifs_setxattr(struct dentry *, const char *, const void *,
-			 size_t, int);
+			size_t, int);
 extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
-#define CIFS_VERSION   "1.31"
+extern int cifs_ioctl (struct inode * inode, struct file * filep,
+		       unsigned int command, unsigned long arg);
+#define CIFS_VERSION   "1.34"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 69aff1a7..81babab 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsglob.h
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -149,6 +149,8 @@
 	__u16 timeZone;
 	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
 	char workstation_RFC1001_name[16]; /* 16th byte is always zero */
+	__u32 sequence_number; /* needed for CIFS PDU signature */
+	char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 
 };
 
 /*
@@ -174,17 +176,16 @@
 	struct TCP_Server_Info *server;	/* pointer to server info */
 	atomic_t inUse; /* # of mounts (tree connections) on this ses */
 	enum statusEnum status;
-	__u32 sequence_number;  /* needed for CIFS PDU signature */
 	__u16 ipc_tid;		/* special tid for connection to IPC share */
 	__u16 flags;
-	char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];	
-	char *serverOS;		/* name of operating system underlying the server */
-	char *serverNOS;	/* name of network operating system that the server is running */
+	char *serverOS;		/* name of operating system underlying server */
+	char *serverNOS;	/* name of network operating system of server */
 	char *serverDomain;	/* security realm of server */
 	int Suid;		/* remote smb uid  */
 	uid_t linux_uid;        /* local Linux uid */
 	int capabilities;
-	char serverName[SERVER_NAME_LEN_WITH_NULL * 2];	/* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
+	char serverName[SERVER_NAME_LEN_WITH_NULL * 2];	/* BB make bigger for 
+				TCP names - will ipv6 and sctp addresses fit? */
 	char userName[MAX_USERNAME_SIZE + 1];
 	char domainName[MAX_USERNAME_SIZE + 1];
 	char * password;
@@ -312,12 +313,15 @@
 	__u16 mid;		/* multiplex id */
 	__u16 pid;		/* process id */
 	__u32 sequence_number;  /* for CIFS signing */
-	__u16 command;		/* smb command code */
 	struct timeval when_sent;	/* time when smb sent */
 	struct cifsSesInfo *ses;	/* smb was sent to this server */
 	struct task_struct *tsk;	/* task waiting for response */
 	struct smb_hdr *resp_buf;	/* response buffer */
 	int midState;	/* wish this were enum but can not pass to wait_event */
+	__u8 command;	/* smb command code */
+	unsigned multiPart:1;	/* multiple responses to one SMB request */
+	unsigned largeBuf:1;    /* if valid response, is pointer to large buf */
+	unsigned multiResp:1;   /* multiple trans2 responses for one request  */
 };
 
 struct oplock_q_entry {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index bcd4a61..aede6a8 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -330,7 +330,7 @@
 };
 /* given a pointer to an smb_hdr retrieve the value of byte count */
 #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
-
+#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
 /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
 #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
 
@@ -762,6 +762,16 @@
 	LOCKING_ANDX_RANGE Locks[1];
 } LOCK_REQ;
 
+
+typedef struct cifs_posix_lock {
+	__le16  lock_type;  /* 0 = Read, 1 = Write, 2 = Unlock */
+	__le16  lock_flags; /* 1 = Wait (only valid for setlock) */
+	__le32  pid;
+	__le64	start;
+	__le64	length;
+	/* BB what about additional owner info to identify network client */
+} CIFS_POSIX_LOCK;
+
 typedef struct smb_com_lock_rsp {
 	struct smb_hdr hdr;	/* wct = 2 */
 	__u8 AndXCommand;
@@ -1098,6 +1108,8 @@
 #define SMB_QUERY_POSIX_ACL             0x204
 #define SMB_QUERY_XATTR                 0x205
 #define SMB_QUERY_ATTR_FLAGS            0x206  /* append,immutable etc. */
+#define SMB_QUERY_POSIX_PERMISSION      0x207
+#define SMB_QUERY_POSIX_LOCK            0x208
 #define SMB_QUERY_FILE_INTERNAL_INFO    0x3ee
 #define SMB_QUERY_FILE_ACCESS_INFO      0x3f0
 #define SMB_QUERY_FILE_NAME_INFO2       0x3f1 /* 0x30 bytes */
@@ -1116,6 +1128,7 @@
 #define SMB_SET_POSIX_ACL               0x204
 #define SMB_SET_XATTR                   0x205
 #define SMB_SET_ATTR_FLAGS              0x206  /* append, immutable etc. */
+#define SMB_SET_POSIX_LOCK              0x208
 #define SMB_SET_FILE_BASIC_INFO2        0x3ec
 #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
 #define SMB_FILE_ALL_INFO2              0x3fa
@@ -1237,9 +1250,25 @@
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
 	struct trans2_resp t2;
 	__u16 ByteCount;
-	__u16 Reserved2;	/* parameter word reserved - present for infolevels > 100 */
+	__u16 Reserved2;	/* parameter word reserved - 
+					present for infolevels > 100 */
 };
 
+struct smb_t2_qfi_req {
+        struct	smb_hdr hdr;
+        struct	trans2_req t2;
+	__u8	Pad;
+	__u16	Fid;
+	__le16	InformationLevel;
+};
+
+struct smb_t2_qfi_rsp {
+        struct smb_hdr hdr;     /* wct = 10 + SetupCount */
+        struct trans2_resp t2;
+        __u16 ByteCount;
+        __u16 Reserved2;        /* parameter word reserved - 
+					present for infolevels > 100 */
+};
 
 /*
  * Flags on T2 FINDFIRST and FINDNEXT 
@@ -1524,9 +1553,10 @@
 } FILE_SYSTEM_UNIX_INFO;	/* Unix extensions info, level 0x200 */
 /* Linux/Unix extensions capability flags */
 #define CIFS_UNIX_FCNTL_CAP             0x00000001 /* support for fcntl locks */
-#define CIFS_UNIX_POSIX_ACL_CAP         0x00000002
-#define CIFS_UNIX_XATTR_CAP             0x00000004 /*support for new namespace*/
-
+#define CIFS_UNIX_POSIX_ACL_CAP         0x00000002 /* support getfacl/setfacl */
+#define CIFS_UNIX_XATTR_CAP             0x00000004 /* support new namespace   */
+#define CIFS_UNIX_EXTATTR_CAP           0x00000008 /* support chattr/chflag   */
+#define CIFS_POSIX_EXTENSIONS           0x00000010 /* support for new QFSInfo */
 typedef struct {
 	/* For undefined recommended transfer size return -1 in that field */
 	__le32 OptimalTransferSize;  /* bsize on some os, iosize on other os */
@@ -1971,15 +2001,40 @@
 	char path[1024];  
 };
 
-typedef struct {
+typedef struct file_xattr_info {
 	/* BB do we need another field for flags? BB */
 	__u32 xattr_name_len;
 	__u32 xattr_value_len;
 	char  xattr_name[0];
 	/* followed by xattr_value[xattr_value_len], no pad */
-} FILE_XATTR_INFO;	/* extended attribute, info level 205 */
+} FILE_XATTR_INFO;	/* extended attribute, info level 0x205 */
 
 
+/* flags for chattr command */
+#define EXT_SECURE_DELETE		0x00000001 /* EXT3_SECRM_FL */
+#define EXT_ENABLE_UNDELETE		0x00000002 /* EXT3_UNRM_FL */
+/* Reserved for compress file 0x4 */
+#define EXT_SYNCHRONOUS			0x00000008 /* EXT3_SYNC_FL */
+#define EXT_IMMUTABLE_FL		0x00000010 /* EXT3_IMMUTABLE_FL */
+#define EXT_OPEN_APPEND_ONLY		0x00000020 /* EXT3_APPEND_FL */
+#define EXT_DO_NOT_BACKUP		0x00000040 /* EXT3_NODUMP_FL */
+#define EXT_NO_UPDATE_ATIME		0x00000080 /* EXT3_NOATIME_FL */
+/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */
+#define EXT_HASH_TREE_INDEXED_DIR	0x00001000 /* GET-ONLY EXT3_INDEX_FL */
+/* 0x2000 reserved for IMAGIC_FL */
+#define EXT_JOURNAL_THIS_FILE	0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */
+/* 0x8000 reserved for EXT3_NOTAIL_FL */
+#define EXT_SYNCHRONOUS_DIR		0x00010000 /* EXT3_DIRSYNC_FL */
+#define EXT_TOPDIR			0x00020000 /* EXT3_TOPDIR_FL */
+
+#define EXT_SET_MASK			0x000300FF
+#define EXT_GET_MASK			0x0003DFFF
+
+typedef struct file_chattr_info {
+	__le64	mask; /* list of all possible attribute bits */
+	__le64	mode; /* list of actual attribute bits on this inode */
+} FILE_CHATTR_INFO;  /* ext attributes (chattr, chflags) level 0x206 */
+
 #endif 
 
 #pragma pack()			/* resume default structure packing */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 787eef4..0010511 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -57,10 +57,11 @@
 extern int cifs_inet_pton(int, char * source, void *dst);
 extern int map_smb_to_linux_error(struct smb_hdr *smb);
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
-			const struct cifsTconInfo *, int
-			/* length of fixed section (word count) in two byte units  */
+			const struct cifsTconInfo *, int /* specifies length
+			    of fixed section (word count) in two byte units */
 			);
-extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
+extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 
+						 struct cifsTconInfo *);
 extern void DeleteOplockQEntry(struct oplock_q_entry *);
 extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
 extern u64 cifs_UnixTimeToNT(struct timespec);
@@ -88,7 +89,7 @@
 
 extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
             const char *searchName, const struct nls_table *nls_codepage,
-            __u16 *searchHandle, struct cifs_search_info * psrch_inf);
+            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
 
 extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
             __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -99,42 +100,42 @@
 extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName,
 			FILE_ALL_INFO * findData,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, int remap);
 
 extern int CIFSSMBUnixQPathInfo(const int xid,
 			struct cifsTconInfo *tcon,
 			const unsigned char *searchName,
 			FILE_UNIX_BASIC_INFO * pFindData,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, int remap);
 
 extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
 			const unsigned char *searchName,
 			unsigned char **targetUNCs,
 			unsigned int *number_of_UNC_in_array,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, int remap);
 
 extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
 			const char *old_path,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, int remap);
 extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
-			const char *old_path, const struct nls_table *nls_codepage, 
-			unsigned int *pnum_referrals, unsigned char ** preferrals);
+			const char *old_path, 
+			const struct nls_table *nls_codepage,
+			unsigned int *pnum_referrals, 
+			unsigned char ** preferrals,
+			int remap);
 extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
-			struct kstatfs *FSData,
-			const struct nls_table *nls_codepage);
+			struct kstatfs *FSData);
 extern int CIFSSMBQFSAttributeInfo(const int xid,
-			struct cifsTconInfo *tcon,
-			const struct nls_table *nls_codepage);
-extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
-			const struct nls_table *nls_codepage);
-extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
-			const struct nls_table *nls_codepage);
+			struct cifsTconInfo *tcon);
+extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
+extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon);
 extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
-			struct kstatfs *FSData, const struct nls_table *nls_codepage);
+			struct kstatfs *FSData);
 
 extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
 			const char *fileName, const FILE_BASIC_INFO * data,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
 			const FILE_BASIC_INFO * data, __u16 fid);
 #if 0
@@ -143,36 +144,49 @@
 			const struct nls_table *nls_codepage);
 #endif /* possibly unneeded function */
 extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
-			const char *fileName, __u64 size,int setAllocationSizeFlag,
-			const struct nls_table *nls_codepage);
+			const char *fileName, __u64 size,
+			int setAllocationSizeFlag,
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
-			 __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
+			 __u64 size, __u16 fileHandle,__u32 opener_pid, 
+			int AllocSizeFlag);
 extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
 			char *full_path, __u64 mode, __u64 uid,
-			__u64 gid, dev_t dev, const struct nls_table *nls_codepage);
+			__u64 gid, dev_t dev, 
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 
 extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
 			const char *newName,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
-			const char *name, const struct nls_table *nls_codepage);
+			const char *name, const struct nls_table *nls_codepage,
+			int remap_special_chars);
 
 extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
 			const char *name,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
 			const char *fromName, const char *toName,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
-			int netfid, char * target_name, const struct nls_table *nls_codepage);
+			int netfid, char * target_name, 
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSCreateHardLink(const int xid,
 			struct cifsTconInfo *tcon,
 			const char *fromName, const char *toName,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern int CIFSUnixCreateHardLink(const int xid,
 			struct cifsTconInfo *tcon,
 			const char *fromName, const char *toName,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, 
+			int remap_special_chars);
 extern int CIFSUnixCreateSymLink(const int xid,
 			struct cifsTconInfo *tcon,
 			const char *fromName, const char *toName,
@@ -192,7 +206,7 @@
 			const char *fileName, const int disposition,
 			const int access_flags, const int omode,
 			__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, int remap);
 extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
 			const int smb_file_id);
 
@@ -211,8 +225,13 @@
 			const char __user *buf,const int long_op);
 extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName, __u64 * inode_number,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, 
+			int remap_special_chars);
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
+extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen,
+			const struct nls_table * codepage);
+extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
+			const struct nls_table * cp, int mapChars);
 
 extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 			const __u16 netfid, const __u64 len,
@@ -230,7 +249,7 @@
 
 extern int cifs_reconnect(struct TCP_Server_Info *server);
 
-extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
+extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
 extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
 	__u32 expected_sequence_number);
 extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
@@ -241,29 +260,31 @@
 			const char *fromName,
 			const __u16 target_tid,
 			const char *toName, const int flags,
-			const struct nls_table *nls_codepage);
+			const struct nls_table *nls_codepage, 
+			int remap_special_chars);
 extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
-			const int notify_subdirs,const __u16 netfid,__u32 filter,
-			const struct nls_table *nls_codepage);
+			const int notify_subdirs,const __u16 netfid,
+			__u32 filter, const struct nls_table *nls_codepage);
 extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName, char * EAData,
-			size_t bufsize, const struct nls_table *nls_codepage);
+			size_t bufsize, const struct nls_table *nls_codepage,
+			int remap_special_chars);
 extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
 		const unsigned char * searchName,const unsigned char * ea_name,
 		unsigned char * ea_value, size_t buf_size, 
-		const struct nls_table *nls_codepage);
+		const struct nls_table *nls_codepage, int remap_special_chars);
 extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 
 		const char *fileName, const char * ea_name, 
 		const void * ea_value, const __u16 ea_value_len, 
-		const struct nls_table *nls_codepage);
+		const struct nls_table *nls_codepage, int remap_special_chars);
 extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
 		const unsigned char *searchName,
 		char *acl_inf, const int buflen,const int acl_type,
-		const struct nls_table *nls_codepage);
+		const struct nls_table *nls_codepage, int remap_special_chars);
 extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
 		const unsigned char *fileName,
 		const char *local_acl, const int buflen, const int acl_type,
-		const struct nls_table *nls_codepage);
-int cifs_ioctl (struct inode * inode, struct file * filep,
-                unsigned int command, unsigned long arg);
+		const struct nls_table *nls_codepage, int remap_special_chars);
+extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
+                const int netfid, __u64 * pExtAttrBits, __u64 *pMask);
 #endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index df6a619..741ff0c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -75,7 +75,8 @@
 		}
 	}
 	write_unlock(&GlobalSMBSeslock);
-	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
+	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
+	   to this tcon */
 }
 
 /* If the return code is zero, this function must fill in request_buf pointer */
@@ -89,11 +90,12 @@
 	   check for tcp and smb session status done differently
 	   for those three - in the calling routine */
 	if(tcon) {
-		if((tcon->ses) && (tcon->ses->server)){
+		if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
+				  (tcon->ses->server)){
 			struct nls_table *nls_codepage;
 				/* Give Demultiplex thread up to 10 seconds to 
-					reconnect, should be greater than cifs socket
-					timeout which is 7 seconds */
+				   reconnect, should be greater than cifs socket
+				   timeout which is 7 seconds */
 			while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
 				wait_event_interruptible_timeout(tcon->ses->server->response_q,
 					(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
@@ -103,8 +105,9 @@
 					   (tcon->ses->status == CifsExiting)) {
 						cFYI(1,("gave up waiting on reconnect in smb_init"));
 						return -EHOSTDOWN;
-					} /* else "hard" mount - keep retrying until 
-					process is killed or server comes back up */
+					} /* else "hard" mount - keep retrying
+					     until process is killed or server
+					     comes back on-line */
 				} else /* TCP session is reestablished now */
 					break;
 				 
@@ -115,23 +118,24 @@
 		simultaneously reconnect the same SMB session */
 			down(&tcon->ses->sesSem);
 			if(tcon->ses->status == CifsNeedReconnect)
-				rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+				rc = cifs_setup_session(0, tcon->ses, 
+							nls_codepage);
 			if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
 				mark_open_files_invalid(tcon);
-				rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
-					nls_codepage);
+				rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
+					, nls_codepage);
 				up(&tcon->ses->sesSem);
 				if(rc == 0)
 					atomic_inc(&tconInfoReconnectCount);
 
 				cFYI(1, ("reconnect tcon rc = %d", rc));
 				/* Removed call to reopen open files here - 
-					it is safer (and faster) to reopen files
-					one at a time as needed in read and write */
+				   it is safer (and faster) to reopen files
+				   one at a time as needed in read and write */
 
 				/* Check if handle based operation so we 
-					know whether we can continue or not without
-					returning to caller to reset file handle */
+				   know whether we can continue or not without
+				   returning to caller to reset file handle */
 				switch(smb_command) {
 					case SMB_COM_READ_ANDX:
 					case SMB_COM_WRITE_ANDX:
@@ -182,22 +186,25 @@
 	   check for tcp and smb session status done differently
 	   for those three - in the calling routine */
 	if(tcon) {
-		if((tcon->ses) && (tcon->ses->server)){
+		if((tcon->ses) && (tcon->ses->status != CifsExiting) && 
+				  (tcon->ses->server)){
 			struct nls_table *nls_codepage;
-				/* Give Demultiplex thread up to 10 seconds to 
-					reconnect, should be greater than cifs socket
-					timeout which is 7 seconds */
+				/* Give Demultiplex thread up to 10 seconds to
+				   reconnect, should be greater than cifs socket
+				   timeout which is 7 seconds */
 			while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
 				wait_event_interruptible_timeout(tcon->ses->server->response_q,
 					(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
-				if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+				if(tcon->ses->server->tcpStatus == 
+						CifsNeedReconnect) {
 					/* on "soft" mounts we wait once */
 					if((tcon->retry == FALSE) || 
 					   (tcon->ses->status == CifsExiting)) {
 						cFYI(1,("gave up waiting on reconnect in smb_init"));
 						return -EHOSTDOWN;
-					} /* else "hard" mount - keep retrying until 
-					process is killed or server comes back up */
+					} /* else "hard" mount - keep retrying
+					     until process is killed or server
+					     comes on-line */
 				} else /* TCP session is reestablished now */
 					break;
 				 
@@ -208,23 +215,24 @@
 		simultaneously reconnect the same SMB session */
 			down(&tcon->ses->sesSem);
 			if(tcon->ses->status == CifsNeedReconnect)
-				rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+				rc = cifs_setup_session(0, tcon->ses, 
+							nls_codepage);
 			if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
 				mark_open_files_invalid(tcon);
-				rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
-					nls_codepage);
+				rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+					      tcon, nls_codepage);
 				up(&tcon->ses->sesSem);
 				if(rc == 0)
 					atomic_inc(&tconInfoReconnectCount);
 
 				cFYI(1, ("reconnect tcon rc = %d", rc));
 				/* Removed call to reopen open files here - 
-					it is safer (and faster) to reopen files
-					one at a time as needed in read and write */
+				   it is safer (and faster) to reopen files
+				   one at a time as needed in read and write */
 
 				/* Check if handle based operation so we 
-					know whether we can continue or not without
-					returning to caller to reset file handle */
+				   know whether we can continue or not without
+				   returning to caller to reset file handle */
 				switch(smb_command) {
 					case SMB_COM_READ_ANDX:
 					case SMB_COM_WRITE_ANDX:
@@ -286,7 +294,8 @@
 			if(total_size < 512) {
 				total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
 				/* BCC le converted in SendReceive */
-				pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 
+				pBCC = (pSMB->hdr.WordCount * 2) + 
+					sizeof(struct smb_hdr) +
 					(char *)pSMB;
 				if((total_size <= (*(u16 *)pBCC)) && 
 				   (total_size < 
@@ -337,8 +346,10 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc == 0) {
 		server->secMode = pSMBr->SecurityMode;	
-		server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
-		/* one byte - no need to convert this or EncryptionKeyLen from le,*/
+		server->secType = NTLM; /* BB override default for 
+					   NTLMv2 or kerberos v5 */
+		/* one byte - no need to convert this or EncryptionKeyLen
+		   from little endian */
 		server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
 		/* probably no need to store and check maxvcs */
 		server->maxBuf =
@@ -374,7 +385,7 @@
 						pSMBr->u.extended_response.
 						GUID, 16) != 0) {
 						cFYI(1,
-							("UID of server does not match previous connection to same ip address"));
+						     ("UID of server does not match previous connection to same ip address"));
 						memcpy(server->
 							server_GUID,
 							pSMBr->u.
@@ -454,17 +465,18 @@
 		up(&tcon->tconSem);
 		return -EIO;
 	}
-	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
+	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, 
+			    (void **)&smb_buffer);
 	if (rc) {
 		up(&tcon->tconSem);
 		return rc;
 	} else {
 		smb_buffer_response = smb_buffer; /* BB removeme BB */
-    }
+	}
 	rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
 			 &length, 0);
 	if (rc)
-		cFYI(1, (" Tree disconnect failed %d", rc));
+		cFYI(1, ("Tree disconnect failed %d", rc));
 
 	if (smb_buffer)
 		cifs_small_buf_release(smb_buffer);
@@ -538,8 +550,8 @@
 }
 
 int
-CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
-	       const char *fileName, const struct nls_table *nls_codepage)
+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+	       const struct nls_table *nls_codepage, int remap)
 {
 	DELETE_FILE_REQ *pSMB = NULL;
 	DELETE_FILE_RSP *pSMBr = NULL;
@@ -555,12 +567,11 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->fileName, fileName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
-	} else {		/* BB improve the check for buffer overruns BB */
+	} else {		/* BB improve check for buffer overruns BB */
 		name_len = strnlen(fileName, PATH_MAX);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->fileName, fileName, name_len);
@@ -589,8 +600,8 @@
 }
 
 int
-CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
-	     const char *dirName, const struct nls_table *nls_codepage)
+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, 
+	     const struct nls_table *nls_codepage, int remap)
 {
 	DELETE_DIRECTORY_REQ *pSMB = NULL;
 	DELETE_DIRECTORY_RSP *pSMBr = NULL;
@@ -606,12 +617,11 @@
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
-				/* find define for this maxpathcomponent */
-				, nls_codepage);
+		name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
+					 PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
-	} else {		/* BB improve the check for buffer overruns BB */
+	} else {		/* BB improve check for buffer overruns BB */
 		name_len = strnlen(dirName, PATH_MAX);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->DirName, dirName, name_len);
@@ -639,7 +649,7 @@
 
 int
 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
-	     const char *name, const struct nls_table *nls_codepage)
+	     const char *name, const struct nls_table *nls_codepage, int remap)
 {
 	int rc = 0;
 	CREATE_DIRECTORY_REQ *pSMB = NULL;
@@ -655,12 +665,11 @@
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
-					 /* find define for this maxpathcomponent */
-					 , nls_codepage);
+		name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name, 
+					    PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
-	} else {		/* BB improve the check for buffer overruns BB */
+	} else {		/* BB improve check for buffer overruns BB */
 		name_len = strnlen(name, PATH_MAX);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->DirName, name, name_len);
@@ -690,7 +699,7 @@
 	    const char *fileName, const int openDisposition,
 	    const int access_flags, const int create_options, __u16 * netfid,
 	    int *pOplock, FILE_ALL_INFO * pfile_info, 
-	    const struct nls_table *nls_codepage)
+	    const struct nls_table *nls_codepage, int remap)
 {
 	int rc = -EACCES;
 	OPEN_REQ *pSMB = NULL;
@@ -710,14 +719,12 @@
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		count = 1;	/* account for one byte pad to word boundary */
 		name_len =
-		    cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
-				  fileName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
+				     fileName, PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 		pSMB->NameLength = cpu_to_le16(name_len);
-	} else {		/* BB improve the check for buffer overruns BB */
+	} else {		/* BB improve check for buffer overruns BB */
 		count = 0;	/* no pad */
 		name_len = strnlen(fileName, PATH_MAX);
 		name_len++;	/* trailing null */
@@ -746,7 +753,8 @@
 	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
 	pSMB->CreateDisposition = cpu_to_le32(openDisposition);
 	pSMB->CreateOptions = cpu_to_le32(create_options);
-	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);	/* BB ??*/
+	/* BB Expirement with various impersonation levels and verify */
+	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
 	pSMB->SecurityFlags =
 	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
 
@@ -760,7 +768,7 @@
 	if (rc) {
 		cFYI(1, ("Error in Open = %d", rc));
 	} else {
-		*pOplock = pSMBr->OplockLevel;	/* one byte no need to le_to_cpu */
+		*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
 		*netfid = pSMBr->Fid;	/* cifs fid stays in le */
 		/* Let caller know file was created so we can set the mode. */
 		/* Do we care about the CreateAction in any other cases? */
@@ -1017,11 +1025,13 @@
 	__u16 count;
 
 	cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
-	rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
+	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
+
 	if (rc)
 		return rc;
 
+	pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
+
 	if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
 		timeout = -1; /* no response expected */
 		pSMB->Timeout = 0;
@@ -1059,7 +1069,7 @@
 	if (rc) {
 		cFYI(1, ("Send error in Lock = %d", rc));
 	}
-	cifs_buf_release(pSMB);
+	cifs_small_buf_release(pSMB);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls 
 	since file handle passed in no longer valid */
@@ -1108,7 +1118,7 @@
 int
 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
 	      const char *fromName, const char *toName,
-	      const struct nls_table *nls_codepage)
+	      const struct nls_table *nls_codepage, int remap)
 {
 	int rc = 0;
 	RENAME_REQ *pSMB = NULL;
@@ -1131,18 +1141,16 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 		pSMB->OldFileName[name_len] = 0x04;	/* pad */
 	/* protocol requires ASCII signature byte on Unicode string */
 		pSMB->OldFileName[name_len + 1] = 0x00;
 		name_len2 =
-		    cifs_strtoUCS((wchar_t *) & pSMB->
-				  OldFileName[name_len + 2], toName, PATH_MAX,
-				  nls_codepage);
+		    cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
+				     toName, PATH_MAX, nls_codepage, remap);
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2;	/* convert to bytes */
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -1182,7 +1190,8 @@
 }
 
 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 
-		int netfid, char * target_name, const struct nls_table * nls_codepage) 
+		int netfid, char * target_name, 
+		const struct nls_table * nls_codepage, int remap)
 {
 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
@@ -1227,9 +1236,11 @@
 	/* unicode only call */
 	if(target_name == NULL) {
 		sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
-	        len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
+	        len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
+					dummy_string, 24, nls_codepage, remap);
 	} else {
-		len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
+		len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
+					target_name, PATH_MAX, nls_codepage, remap);
 	}
 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
 	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
@@ -1263,7 +1274,7 @@
 int
 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
             const __u16 target_tid, const char *toName, const int flags,
-            const struct nls_table *nls_codepage)
+            const struct nls_table *nls_codepage, int remap)
 {
 	int rc = 0;
 	COPY_REQ *pSMB = NULL;
@@ -1285,18 +1296,16 @@
 	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
-				fromName, 
-				PATH_MAX /* find define for this maxpathcomponent */,
-				nls_codepage);
+		name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName, 
+					    fromName, PATH_MAX, nls_codepage,
+					    remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 		pSMB->OldFileName[name_len] = 0x04;     /* pad */
 		/* protocol requires ASCII signature byte on Unicode string */
 		pSMB->OldFileName[name_len + 1] = 0x00;
-		name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
-				OldFileName[name_len + 2], toName, PATH_MAX,
-				nls_codepage);
+		name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], 
+				toName, PATH_MAX, nls_codepage, remap);
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2; /* convert to bytes */
 	} else {                /* BB improve the check for buffer overruns BB */
@@ -1425,7 +1434,7 @@
 int
 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
 		       const char *fromName, const char *toName,
-		       const struct nls_table *nls_codepage)
+		       const struct nls_table *nls_codepage, int remap)
 {
 	TRANSACTION2_SPI_REQ *pSMB = NULL;
 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -1444,9 +1453,8 @@
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
-					 /* find define for this maxpathcomponent */
-					 , nls_codepage);
+		name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
+					    PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 
@@ -1468,9 +1476,8 @@
 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
-		    cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
+				     nls_codepage, remap);
 		name_len_target++;	/* trailing null */
 		name_len_target *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -1512,7 +1519,7 @@
 int
 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
 		   const char *fromName, const char *toName,
-		   const struct nls_table *nls_codepage)
+		   const struct nls_table *nls_codepage, int remap)
 {
 	int rc = 0;
 	NT_RENAME_REQ *pSMB = NULL;
@@ -1539,17 +1546,15 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 		pSMB->OldFileName[name_len] = 0;	/* pad */
 		pSMB->OldFileName[name_len + 1] = 0x04; 
 		name_len2 =
-		    cifs_strtoUCS((wchar_t *) & pSMB->
-				  OldFileName[name_len + 2], toName, PATH_MAX,
-				  nls_codepage);
+		    cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], 
+				     toName, PATH_MAX, nls_codepage, remap);
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2;	/* convert to bytes */
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -1659,6 +1664,7 @@
 				name_len = UniStrnlen((wchar_t *) ((char *)
 					&pSMBr->hdr.Protocol +data_offset),
 					min_t(const int, buflen,count) / 2);
+			/* BB FIXME investigate remapping reserved chars here */
 				cifs_strfromUCS_le(symlinkinfo,
 					(wchar_t *) ((char *)&pSMBr->hdr.Protocol +
 						data_offset),
@@ -1793,7 +1799,8 @@
 }
 
 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
-static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
+static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
+				const int acl_type,const int size_of_data_area)
 {
 	int size =  0;
 	int i;
@@ -1912,7 +1919,7 @@
 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
                         const unsigned char *searchName,
                         char *acl_inf, const int buflen, const int acl_type,
-                        const struct nls_table *nls_codepage)
+                        const struct nls_table *nls_codepage, int remap)
 {
 /* SMB_QUERY_POSIX_ACL */
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -1932,8 +1939,8 @@
                                                                                                                                              
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-				, nls_codepage);
+			cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 
+					 PATH_MAX, nls_codepage, remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 		pSMB->FileName[name_len] = 0;
@@ -1997,8 +2004,9 @@
 int
 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
                         const unsigned char *fileName,
-                        const char *local_acl, const int buflen, const int acl_type,
-                        const struct nls_table *nls_codepage)
+                        const char *local_acl, const int buflen, 
+			const int acl_type,
+                        const struct nls_table *nls_codepage, int remap)
 {
 	struct smb_com_transaction2_spi_req *pSMB = NULL;
 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -2016,8 +2024,8 @@
 		return rc;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-				, nls_codepage);
+			cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 
+				      PATH_MAX, nls_codepage, remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {                /* BB improve the check for buffer overruns BB */
@@ -2072,13 +2080,96 @@
 	return rc;
 }
 
-#endif
+/* BB fix tabs in this function FIXME BB */
+int
+CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
+                const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
+{
+        int rc = 0;
+        struct smb_t2_qfi_req *pSMB = NULL;
+        struct smb_t2_qfi_rsp *pSMBr = NULL;
+        int bytes_returned;
+        __u16 params, byte_count;
+
+        cFYI(1,("In GetExtAttr"));
+        if(tcon == NULL)
+                return -ENODEV;
+
+GetExtAttrRetry:
+        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+        if (rc)
+                return rc;
+
+        params = 2 /* level */ +2 /* fid */;
+        pSMB->t2.TotalDataCount = 0;
+        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+        /* BB find exact max data count below from sess structure BB */
+        pSMB->t2.MaxDataCount = cpu_to_le16(4000);
+        pSMB->t2.MaxSetupCount = 0;
+        pSMB->t2.Reserved = 0;
+        pSMB->t2.Flags = 0;
+        pSMB->t2.Timeout = 0;
+        pSMB->t2.Reserved2 = 0;
+        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+			Fid) - 4);
+        pSMB->t2.DataCount = 0;
+        pSMB->t2.DataOffset = 0;
+        pSMB->t2.SetupCount = 1;
+        pSMB->t2.Reserved3 = 0;
+        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+        byte_count = params + 1 /* pad */ ;
+        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
+        pSMB->Pad = 0;
+	pSMB->Fid = netfid;
+        pSMB->hdr.smb_buf_length += byte_count;
+        pSMB->t2.ByteCount = cpu_to_le16(byte_count);
+
+        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+        if (rc) {
+                cFYI(1, ("error %d in GetExtAttr", rc));
+        } else {
+                /* decode response */
+                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+                if (rc || (pSMBr->ByteCount < 2))
+                /* BB also check enough total bytes returned */
+                        /* If rc should we check for EOPNOSUPP and
+                        disable the srvino flag? or in caller? */
+                        rc = -EIO;      /* bad smb */
+                else {
+                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+                        struct file_chattr_info * pfinfo;
+                        /* BB Do we need a cast or hash here ? */
+                        if(count != 16) {
+                                cFYI(1, ("Illegal size ret in GetExtAttr"));
+                                rc = -EIO;
+                                goto GetExtAttrOut;
+                        }
+                        pfinfo = (struct file_chattr_info *)
+                                (data_offset + (char *) &pSMBr->hdr.Protocol);
+                        *pExtAttrBits = le64_to_cpu(pfinfo->mode);
+			*pMask = le64_to_cpu(pfinfo->mask);
+                }
+        }
+GetExtAttrOut:
+        cifs_buf_release(pSMB);
+        if (rc == -EAGAIN)
+                goto GetExtAttrRetry;
+        return rc;
+}
+
+
+#endif /* CONFIG_POSIX */
 
 int
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 		 const unsigned char *searchName,
 		 FILE_ALL_INFO * pFindData,
-		 const struct nls_table *nls_codepage)
+		 const struct nls_table *nls_codepage, int remap)
 {
 /* level 263 SMB_QUERY_FILE_ALL_INFO */
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2097,9 +2188,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -2160,7 +2250,7 @@
 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
 		     const unsigned char *searchName,
 		     FILE_UNIX_BASIC_INFO * pFindData,
-		     const struct nls_table *nls_codepage)
+		     const struct nls_table *nls_codepage, int remap)
 {
 /* SMB_QUERY_FILE_UNIX_BASIC */
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2179,9 +2269,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+				  PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -2261,7 +2350,7 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+		    cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
 				  /* find define for this maxpathcomponent */
 				  , nls_codepage);
 		name_len++;	/* trailing null */
@@ -2325,7 +2414,7 @@
 	      const char *searchName, 
 	      const struct nls_table *nls_codepage,
 	      __u16 *	pnetfid,
-	      struct cifs_search_info * psrch_inf)
+	      struct cifs_search_info * psrch_inf, int remap)
 {
 /* level 257 SMB_ */
 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2336,7 +2425,7 @@
 	int name_len;
 	__u16 params, byte_count;
 
-	cFYI(1, ("In FindFirst"));
+	cFYI(1, ("In FindFirst for %s",searchName));
 
 findFirstRetry:
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2346,20 +2435,30 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
-				 PATH_MAX, nls_codepage);
-		name_len++;	/* trailing null */
+		    cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
+				 PATH_MAX, nls_codepage, remap);
+		/* We can not add the asterik earlier in case
+		it got remapped to 0xF03A as if it were part of the
+		directory name instead of a wildcard */
 		name_len *= 2;
+		pSMB->FileName[name_len] = '\\';
+		pSMB->FileName[name_len+1] = 0;
+		pSMB->FileName[name_len+2] = '*';
+		pSMB->FileName[name_len+3] = 0;
+		name_len += 4; /* now the trailing null */
 		pSMB->FileName[name_len] = 0; /* null terminate just in case */
 		pSMB->FileName[name_len+1] = 0;
+		name_len += 2;
 	} else {	/* BB add check for overrun of SMB buf BB */
 		name_len = strnlen(searchName, PATH_MAX);
-		name_len++;	/* trailing null */
 /* BB fix here and in unicode clause above ie
 		if(name_len > buffersize-header)
 			free buffer exit; BB */
 		strncpy(pSMB->FileName, searchName, name_len);
-		pSMB->FileName[name_len] = 0; /* just in case */
+		pSMB->FileName[name_len] = '\\';
+		pSMB->FileName[name_len+1] = '*';
+		pSMB->FileName[name_len+2] = 0;
+		name_len += 3;
 	}
 
 	params = 12 + name_len /* includes null */ ;
@@ -2422,7 +2521,6 @@
 			psrch_inf->srch_entries_start = 
 				(char *) &pSMBr->hdr.Protocol + 
 					le16_to_cpu(pSMBr->t2.DataOffset);
-
 			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
 			       le16_to_cpu(pSMBr->t2.ParameterOffset));
 
@@ -2434,7 +2532,6 @@
 			psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
 			psrch_inf->index_of_last_entry = 
 				psrch_inf->entries_in_buffer;
-/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry));  */
 			*pnetfid = parms->SearchHandle;
 		} else {
 			cifs_buf_release(pSMB);
@@ -2608,7 +2705,7 @@
 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
                 __u64 * inode_number,
-                const struct nls_table *nls_codepage)
+                const struct nls_table *nls_codepage, int remap)
 {
 	int rc = 0;
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2629,8 +2726,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 
-				PATH_MAX,nls_codepage);
+			cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+				PATH_MAX,nls_codepage, remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {                /* BB improve the check for buffer overruns BB */
@@ -2704,7 +2801,7 @@
 		const unsigned char *searchName,
 		unsigned char **targetUNCs,
 		unsigned int *number_of_UNC_in_array,
-		const struct nls_table *nls_codepage)
+		const struct nls_table *nls_codepage, int remap)
 {
 /* TRANS2_GET_DFS_REFERRAL */
 	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
@@ -2740,10 +2837,8 @@
 	if (ses->capabilities & CAP_UNICODE) {
 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
-				  searchName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
+				     searchName, PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -2871,8 +2966,7 @@
 }
 
 int
-CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
-	       struct kstatfs *FSData, const struct nls_table *nls_codepage)
+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
 {
 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -2955,8 +3049,7 @@
 }
 
 int
-CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
-			const struct nls_table *nls_codepage)
+CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
 {
 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3024,8 +3117,7 @@
 }
 
 int
-CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
-		     const struct nls_table *nls_codepage)
+CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
 {
 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3078,8 +3170,8 @@
 		else {
 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
 			response_data =
-			    (FILE_SYSTEM_DEVICE_INFO
-			     *) (((char *) &pSMBr->hdr.Protocol) +
+			    (FILE_SYSTEM_DEVICE_INFO *)
+				(((char *) &pSMBr->hdr.Protocol) +
 				 data_offset);
 			memcpy(&tcon->fsDevInfo, response_data,
 			       sizeof (FILE_SYSTEM_DEVICE_INFO));
@@ -3094,8 +3186,7 @@
 }
 
 int
-CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
-		   const struct nls_table *nls_codepage)
+CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
 {
 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3166,7 +3257,7 @@
 
 int
 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
-		   struct kstatfs *FSData, const struct nls_table *nls_codepage)
+		   struct kstatfs *FSData)
 {
 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3258,7 +3349,8 @@
 
 int
 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
-	      __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
+	      __u64 size, int SetAllocation, 
+	      const struct nls_table *nls_codepage, int remap)
 {
 	struct smb_com_transaction2_spi_req *pSMB = NULL;
 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -3277,9 +3369,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -3360,11 +3451,13 @@
 
 	cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
 			(long long)size));
-	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
+	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
 	if (rc)
 		return rc;
 
+	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
+
 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
     
@@ -3424,7 +3517,7 @@
 	}
 
 	if (pSMB)
-		cifs_buf_release(pSMB);
+		cifs_small_buf_release(pSMB);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls 
 		since file handle passed in no longer valid */
@@ -3450,11 +3543,13 @@
 	__u16 params, param_offset, offset, byte_count, count;
 
 	cFYI(1, ("Set Times (via SetFileInfo)"));
-	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
+	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
 	if (rc)
 		return rc;
 
+	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
+
 	/* At this point there is no need to override the current pid
 	with the pid of the opener, but that could change if we someday
 	use an existing handle (rather than opening one on the fly) */
@@ -3500,7 +3595,7 @@
 		cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
 	}
 
-	cifs_buf_release(pSMB);
+	cifs_small_buf_release(pSMB);
 
 	/* Note: On -EAGAIN error only caller can retry on handle based calls 
 		since file handle passed in no longer valid */
@@ -3512,7 +3607,7 @@
 int
 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 		const FILE_BASIC_INFO * data, 
-		const struct nls_table *nls_codepage)
+		const struct nls_table *nls_codepage, int remap)
 {
 	TRANSACTION2_SPI_REQ *pSMB = NULL;
 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3532,9 +3627,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -3614,7 +3708,7 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 
+			ConvertToUCS((wchar_t *) pSMB->fileName, fileName, 
 				PATH_MAX, nls_codepage);
 		name_len++;     /* trailing null */
 		name_len *= 2;
@@ -3644,8 +3738,9 @@
 
 int
 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
-		    char *fileName, __u64 mode, __u64 uid, __u64 gid,
-		    dev_t device, const struct nls_table *nls_codepage)
+		    char *fileName, __u64 mode, __u64 uid, __u64 gid, 
+		    dev_t device, const struct nls_table *nls_codepage, 
+		    int remap)
 {
 	TRANSACTION2_SPI_REQ *pSMB = NULL;
 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3664,9 +3759,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
@@ -3789,7 +3883,7 @@
 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
 		 const unsigned char *searchName,
 		 char * EAData, size_t buf_size,
-		 const struct nls_table *nls_codepage)
+		 const struct nls_table *nls_codepage, int remap)
 {
 		/* BB assumes one setup word */
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -3810,9 +3904,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -3934,7 +4027,7 @@
 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
 		const unsigned char * searchName,const unsigned char * ea_name,
 		unsigned char * ea_value, size_t buf_size, 
-		const struct nls_table *nls_codepage)
+		const struct nls_table *nls_codepage, int remap)
 {
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
@@ -3954,9 +4047,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -4082,7 +4174,8 @@
 int
 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 		const char * ea_name, const void * ea_value, 
-		const __u16 ea_value_len, const struct nls_table *nls_codepage)
+		const __u16 ea_value_len, const struct nls_table *nls_codepage,
+		int remap)
 {
 	struct smb_com_transaction2_spi_req *pSMB = NULL;
 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -4101,9 +4194,8 @@
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, 
+				     PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 40470b9..e568cc4 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/connect.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/utsname.h>
 #include <linux/mempool.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include "cifspdu.h"
@@ -72,6 +73,7 @@
 	unsigned no_xattr:1;   /* set if xattr (EA) support should be disabled*/
 	unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
 	unsigned direct_io:1;
+	unsigned remap:1;   /* set to remap seven reserved chars in filenames */
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int sockopt;
@@ -114,7 +116,7 @@
 	spin_unlock(&GlobalMid_Lock);
 	server->maxBuf = 0;
 
-	cFYI(1, ("Reconnecting tcp session "));
+	cFYI(1, ("Reconnecting tcp session"));
 
 	/* before reconnecting the tcp session, mark the smb session (uid)
 		and the tid bad so they are not used until reconnected */
@@ -155,9 +157,10 @@
 					qhead);
 		if(mid_entry) {
 			if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
-				/* Mark other intransit requests as needing retry so 
-				  we do not immediately mark the session bad again 
-				  (ie after we reconnect below) as they timeout too */
+				/* Mark other intransit requests as needing
+				   retry so we do not immediately mark the
+				   session bad again (ie after we reconnect
+				   below) as they timeout too */
 				mid_entry->midState = MID_RETRY_NEEDED;
 			}
 		}
@@ -175,14 +178,14 @@
 					server->workstation_RFC1001_name);
 		}
 		if(rc) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(3 * HZ);
+			msleep(3000);
 		} else {
 			atomic_inc(&tcpSesReconnectCount);
 			spin_lock(&GlobalMid_Lock);
 			if(server->tcpStatus != CifsExiting)
 				server->tcpStatus = CifsGood;
-			spin_unlock(&GlobalMid_Lock);
+			server->sequence_number = 0;
+			spin_unlock(&GlobalMid_Lock);			
 	/*		atomic_set(&server->inFlight,0);*/
 			wake_up(&server->response_q);
 		}
@@ -190,12 +193,129 @@
 	return rc;
 }
 
+/* 
+	return codes:
+		0 	not a transact2, or all data present
+		>0 	transact2 with that much data missing
+		-EINVAL = invalid transact2
+
+ */
+static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
+{
+	struct smb_t2_rsp * pSMBt;
+        int total_data_size;
+	int data_in_this_rsp;
+	int remaining;
+
+	if(pSMB->Command != SMB_COM_TRANSACTION2)
+		return 0;
+
+        /* check for plausible wct, bcc and t2 data and parm sizes */
+        /* check for parm and data offset going beyond end of smb */
+	if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
+		cFYI(1,("invalid transact2 word count"));
+		return -EINVAL;
+	}
+
+	pSMBt = (struct smb_t2_rsp *)pSMB;
+
+	total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
+	data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
+
+	remaining = total_data_size - data_in_this_rsp;
+
+	if(remaining == 0)
+		return 0;
+	else if(remaining < 0) {
+		cFYI(1,("total data %d smaller than data in frame %d",
+			total_data_size, data_in_this_rsp));
+		return -EINVAL;
+	} else {
+		cFYI(1,("missing %d bytes from transact2, check next response",
+			remaining));
+		if(total_data_size > maxBufSize) {
+			cERROR(1,("TotalDataSize %d is over maximum buffer %d",
+				total_data_size,maxBufSize));
+			return -EINVAL; 
+		}
+		return remaining;
+	}
+}
+
+static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
+{
+	struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
+	struct smb_t2_rsp *pSMBt  = (struct smb_t2_rsp *)pTargetSMB;
+	int total_data_size;
+	int total_in_buf;
+	int remaining;
+	int total_in_buf2;
+	char * data_area_of_target;
+	char * data_area_of_buf2;
+	__u16 byte_count;
+
+	total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
+
+	if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
+		cFYI(1,("total data sizes of primary and secondary t2 differ"));
+	}
+
+	total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
+
+	remaining = total_data_size - total_in_buf;
+	
+	if(remaining < 0)
+		return -EINVAL;
+
+	if(remaining == 0) /* nothing to do, ignore */
+		return 0;
+	
+	total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
+	if(remaining < total_in_buf2) {
+		cFYI(1,("transact2 2nd response contains too much data"));
+	}
+
+	/* find end of first SMB data area */
+	data_area_of_target = (char *)&pSMBt->hdr.Protocol + 
+				le16_to_cpu(pSMBt->t2_rsp.DataOffset);
+	/* validate target area */
+
+	data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
+                                        le16_to_cpu(pSMB2->t2_rsp.DataOffset);
+
+	data_area_of_target += total_in_buf;
+
+	/* copy second buffer into end of first buffer */
+	memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
+	total_in_buf += total_in_buf2;
+	pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
+	byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
+	byte_count += total_in_buf2;
+	BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
+
+	byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
+	byte_count += total_in_buf2;
+
+	/* BB also add check that we are not beyond maximum buffer size */
+		
+	pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
+
+	if(remaining == total_in_buf2) {
+		cFYI(1,("found the last secondary response"));
+		return 0; /* we are done */
+	} else /* more responses to go */
+		return 1;
+
+}
+
 static int
 cifs_demultiplex_thread(struct TCP_Server_Info *server)
 {
 	int length;
 	unsigned int pdu_length, total_read;
 	struct smb_hdr *smb_buffer = NULL;
+	struct smb_hdr *bigbuf = NULL;
+	struct smb_hdr *smallbuf = NULL;
 	struct msghdr smb_msg;
 	struct kvec iov;
 	struct socket *csocket = server->ssocket;
@@ -204,6 +324,9 @@
 	struct task_struct *task_to_wake = NULL;
 	struct mid_q_entry *mid_entry;
 	char *temp;
+	int isLargeBuf = FALSE;
+	int isMultiRsp;
+	int reconnect;
 
 	daemonize("cifsd");
 	allow_signal(SIGKILL);
@@ -221,17 +344,34 @@
 	}
 
 	while (server->tcpStatus != CifsExiting) {
-		if (smb_buffer == NULL)
-			smb_buffer = cifs_buf_get();
-		else
-			memset(smb_buffer, 0, sizeof (struct smb_hdr));
-
-		if (smb_buffer == NULL) {
-			cERROR(1,("Can not get memory for SMB response"));
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ * 3); /* give system time to free memory */
-			continue;
+		if (bigbuf == NULL) {
+			bigbuf = cifs_buf_get();
+			if(bigbuf == NULL) {
+				cERROR(1,("No memory for large SMB response"));
+				msleep(3000);
+				/* retry will check if exiting */
+				continue;
+			}
+		} else if(isLargeBuf) {
+			/* we are reusing a dirtry large buf, clear its start */
+			memset(bigbuf, 0, sizeof (struct smb_hdr));
 		}
+
+		if (smallbuf == NULL) {
+			smallbuf = cifs_small_buf_get();
+			if(smallbuf == NULL) {
+				cERROR(1,("No memory for SMB response"));
+				msleep(1000);
+				/* retry will check if exiting */
+				continue;
+			}
+			/* beginning of smb buffer is cleared in our buf_get */
+		} else /* if existing small buf clear beginning */
+			memset(smallbuf, 0, sizeof (struct smb_hdr));
+
+		isLargeBuf = FALSE;
+		isMultiRsp = FALSE;
+		smb_buffer = smallbuf;
 		iov.iov_base = smb_buffer;
 		iov.iov_len = 4;
 		smb_msg.msg_control = NULL;
@@ -243,176 +383,257 @@
 		if(server->tcpStatus == CifsExiting) {
 			break;
 		} else if (server->tcpStatus == CifsNeedReconnect) {
-			cFYI(1,("Reconnecting after server stopped responding"));
+			cFYI(1,("Reconnect after server stopped responding"));
 			cifs_reconnect(server);
 			cFYI(1,("call to reconnect done"));
 			csocket = server->ssocket;
 			continue;
 		} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1); /* minimum sleep to prevent looping
+			msleep(1); /* minimum sleep to prevent looping
 				allowing socket to clear and app threads to set
 				tcpStatus CifsNeedReconnect if server hung */
 			continue;
 		} else if (length <= 0) {
 			if(server->tcpStatus == CifsNew) {
-				cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
-				/* some servers kill tcp session rather than returning
-					smb negprot error in which case reconnecting here is
-					not going to help - return error to mount */
+				cFYI(1,("tcp session abend after SMBnegprot"));
+				/* some servers kill the TCP session rather than
+				   returning an SMB negprot error, in which
+				   case reconnecting here is not going to help,
+				   and so simply return error to mount */
 				break;
 			}
 			if(length == -EINTR) { 
 				cFYI(1,("cifsd thread killed"));
 				break;
 			}
-			cFYI(1,("Reconnecting after unexpected peek error %d",length));
+			cFYI(1,("Reconnect after unexpected peek error %d",
+				length));
 			cifs_reconnect(server);
 			csocket = server->ssocket;
 			wake_up(&server->response_q);
 			continue;
-		} else if (length > 3) {
-			pdu_length = ntohl(smb_buffer->smb_buf_length);
-		/* Only read pdu_length after below checks for too short (due
-		   to e.g. int overflow) and too long ie beyond end of buf */
-			cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
-
-			temp = (char *) smb_buffer;
-			if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
-				cFYI(0,("Received 4 byte keep alive packet"));
-			} else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
-					cFYI(1,("Good RFC 1002 session rsp"));
-			} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
-				/* we get this from Windows 98 instead of error on SMB negprot response */
-				cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
-				if(server->tcpStatus == CifsNew) {
-					/* if nack on negprot (rather than 
-					ret of smb negprot error) reconnecting
-					not going to help, ret error to mount */
-					break;
-				} else {
-					/* give server a second to
-					clean up before reconnect attempt */
-					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ);
-					/* always try 445 first on reconnect
-					since we get NACK on some if we ever
-					connected to port 139 (the NACK is 
-					since we do not begin with RFC1001
-					session initialize frame) */
-					server->addr.sockAddr.sin_port = htons(CIFS_PORT);
-					cifs_reconnect(server);
-					csocket = server->ssocket;
-					wake_up(&server->response_q);
-					continue;
-				}
-			} else if (temp[0] != (char) 0) {
-				cERROR(1,("Unknown RFC 1002 frame"));
-				cifs_dump_mem(" Received Data: ", temp, length);
-				cifs_reconnect(server);
-				csocket = server->ssocket;
-				continue;
-			} else {
-				if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
-				    || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
-					cERROR(1,
-					    ("Invalid size SMB length %d and pdu_length %d",
-						length, pdu_length+4));
-					cifs_reconnect(server);
-					csocket = server->ssocket;
-					wake_up(&server->response_q);
-					continue;
-				} else { /* length ok */
-					length = 0;
-					iov.iov_base = 4 + (char *)smb_buffer;
-					iov.iov_len = pdu_length;
-					for (total_read = 0; 
-					     total_read < pdu_length;
-					     total_read += length) {
-						length = kernel_recvmsg(csocket, &smb_msg, 
-							&iov, 1,
-							pdu_length - total_read, 0);
-						if (length == 0) {
-							cERROR(1,
-							       ("Zero length receive when expecting %d ",
-								pdu_length - total_read));
-							cifs_reconnect(server);
-							csocket = server->ssocket;
-							wake_up(&server->response_q);
-							continue;
-						}
-					}
-					length += 4; /* account for rfc1002 hdr */
-				}
-
-				dump_smb(smb_buffer, length);
-				if (checkSMB
-				    (smb_buffer, smb_buffer->Mid, total_read+4)) {
-					cERROR(1, ("Bad SMB Received "));
-					continue;
-				}
-
-				task_to_wake = NULL;
-				spin_lock(&GlobalMid_Lock);
-				list_for_each(tmp, &server->pending_mid_q) {
-					mid_entry = list_entry(tmp, struct
-							       mid_q_entry,
-							       qhead);
-
-					if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
-						cFYI(1,
-						     (" Mid 0x%x matched - waking up ",mid_entry->mid));
-						task_to_wake = mid_entry->tsk;
-						mid_entry->resp_buf =
-						    smb_buffer;
-						mid_entry->midState =
-						    MID_RESPONSE_RECEIVED;
-					}
-				}
-				spin_unlock(&GlobalMid_Lock);
-				if (task_to_wake) {
-					smb_buffer = NULL;	/* will be freed by users thread after he is done */
-					wake_up_process(task_to_wake);
-				} else if (is_valid_oplock_break(smb_buffer) == FALSE) {                          
-					cERROR(1, ("No task to wake, unknown frame rcvd!"));
-					cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
-				}
-			}
-		} else {
+		} else if (length < 4) {
 			cFYI(1,
-			    ("Frame less than four bytes received  %d bytes long.",
+			    ("Frame under four bytes received (%d bytes long)",
 			      length));
 			cifs_reconnect(server);
 			csocket = server->ssocket;
 			wake_up(&server->response_q);
 			continue;
 		}
-	}
+
+		/* the right amount was read from socket - 4 bytes */
+
+		pdu_length = ntohl(smb_buffer->smb_buf_length);
+		cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
+
+		temp = (char *) smb_buffer;
+		if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
+			continue; 
+		} else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
+			cFYI(1,("Good RFC 1002 session rsp"));
+			continue;
+		} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+			/* we get this from Windows 98 instead of 
+			   an error on SMB negprot response */
+			cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
+				temp[4]));
+			if(server->tcpStatus == CifsNew) {
+				/* if nack on negprot (rather than 
+				ret of smb negprot error) reconnecting
+				not going to help, ret error to mount */
+				break;
+			} else {
+				/* give server a second to
+				clean up before reconnect attempt */
+				msleep(1000);
+				/* always try 445 first on reconnect
+				since we get NACK on some if we ever
+				connected to port 139 (the NACK is 
+				since we do not begin with RFC1001
+				session initialize frame) */
+				server->addr.sockAddr.sin_port = 
+					htons(CIFS_PORT);
+				cifs_reconnect(server);
+				csocket = server->ssocket;
+				wake_up(&server->response_q);
+				continue;
+			}
+		} else if (temp[0] != (char) 0) {
+			cERROR(1,("Unknown RFC 1002 frame"));
+			cifs_dump_mem(" Received Data: ", temp, length);
+			cifs_reconnect(server);
+			csocket = server->ssocket;
+			continue;
+		}
+
+		/* else we have an SMB response */
+		if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
+			    (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
+			cERROR(1, ("Invalid size SMB length %d pdu_length %d",
+					length, pdu_length+4));
+			cifs_reconnect(server);
+			csocket = server->ssocket;
+			wake_up(&server->response_q);
+			continue;
+		} 
+
+		/* else length ok */
+		reconnect = 0;
+
+		if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
+			isLargeBuf = TRUE;
+			memcpy(bigbuf, smallbuf, 4);
+			smb_buffer = bigbuf;
+		}
+		length = 0;
+		iov.iov_base = 4 + (char *)smb_buffer;
+		iov.iov_len = pdu_length;
+		for (total_read = 0; total_read < pdu_length; 
+		     total_read += length) {
+			length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
+						pdu_length - total_read, 0);
+			if((server->tcpStatus == CifsExiting) ||
+			    (length == -EINTR)) {
+				/* then will exit */
+				reconnect = 2;
+				break;
+			} else if (server->tcpStatus == CifsNeedReconnect) {
+				cifs_reconnect(server);
+				csocket = server->ssocket;
+			        /* Reconnect wakes up rspns q */
+				/* Now we will reread sock */
+				reconnect = 1;
+				break;
+			} else if ((length == -ERESTARTSYS) || 
+				   (length == -EAGAIN)) {
+				msleep(1); /* minimum sleep to prevent looping,
+                                              allowing socket to clear and app 
+					      threads to set tcpStatus
+					      CifsNeedReconnect if server hung*/
+				continue;
+			} else if (length <= 0) {
+				cERROR(1,("Received no data, expecting %d",
+					      pdu_length - total_read));
+				cifs_reconnect(server);
+				csocket = server->ssocket;
+				reconnect = 1;
+				break;
+			}
+		}
+		if(reconnect == 2)
+			break;
+		else if(reconnect == 1)
+			continue;
+
+		length += 4; /* account for rfc1002 hdr */
+	
+
+		dump_smb(smb_buffer, length);
+		if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
+			cERROR(1, ("Bad SMB Received "));
+			continue;
+		}
+
+
+		task_to_wake = NULL;
+		spin_lock(&GlobalMid_Lock);
+		list_for_each(tmp, &server->pending_mid_q) {
+			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+
+			if ((mid_entry->mid == smb_buffer->Mid) && 
+			    (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
+			    (mid_entry->command == smb_buffer->Command)) {
+				if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
+					/* We have a multipart transact2 resp */
+					isMultiRsp = TRUE;
+					if(mid_entry->resp_buf) {
+						/* merge response - fix up 1st*/
+						if(coalesce_t2(smb_buffer, 
+							mid_entry->resp_buf)) {
+							break;
+						} else {
+							/* all parts received */
+							goto multi_t2_fnd; 
+						}
+					} else {
+						if(!isLargeBuf) {
+							cERROR(1,("1st trans2 resp needs bigbuf"));
+					/* BB maybe we can fix this up,  switch
+				   	   to already allocated large buffer? */
+						} else {
+							/* Have first buffer */
+							mid_entry->resp_buf =
+								 smb_buffer;
+							mid_entry->largeBuf = 1;
+							bigbuf = NULL;
+						}
+					}
+					break;
+				} 
+				mid_entry->resp_buf = smb_buffer;
+				if(isLargeBuf)
+					mid_entry->largeBuf = 1;
+				else
+					mid_entry->largeBuf = 0;
+multi_t2_fnd:
+				task_to_wake = mid_entry->tsk;
+				mid_entry->midState = MID_RESPONSE_RECEIVED;
+				break;
+			}
+		}
+		spin_unlock(&GlobalMid_Lock);
+		if (task_to_wake) {
+			/* Was previous buf put in mpx struct for multi-rsp? */
+			if(!isMultiRsp) {
+				/* smb buffer will be freed by user thread */
+				if(isLargeBuf) {
+					bigbuf = NULL;
+				} else
+					smallbuf = NULL;
+			}
+			wake_up_process(task_to_wake);
+		} else if ((is_valid_oplock_break(smb_buffer) == FALSE)
+		    && (isMultiRsp == FALSE)) {                          
+			cERROR(1, ("No task to wake, unknown frame rcvd!"));
+			cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+		}
+	} /* end while !EXITING */
+
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
 	server->tsk = NULL;
-	atomic_set(&server->inFlight, 0);
+	/* check if we have blocked requests that need to free */
+	/* Note that cifs_max_pending is normally 50, but
+	can be set at module install time to as little as two */
+	if(atomic_read(&server->inFlight) >= cifs_max_pending)
+		atomic_set(&server->inFlight, cifs_max_pending - 1);
+	/* We do not want to set the max_pending too low or we
+	could end up with the counter going negative */
 	spin_unlock(&GlobalMid_Lock);
 	/* Although there should not be any requests blocked on 
 	this queue it can not hurt to be paranoid and try to wake up requests
-	that may haven been blocked when more than 50 at time were on the wire 
+	that may haven been blocked when more than 50 at time were on the wire
 	to the same server - they now will see the session is in exit state
 	and get out of SendReceive.  */
 	wake_up_all(&server->request_q);
 	/* give those requests time to exit */
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/8);
-
+	msleep(125);
+	
 	if(server->ssocket) {
 		sock_release(csocket);
 		server->ssocket = NULL;
 	}
-	if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
-		cifs_buf_release(smb_buffer);
+	/* buffer usuallly freed in free_mid - need to free it here on exit */
+	if (bigbuf != NULL)
+		cifs_buf_release(bigbuf);
+	if (smallbuf != NULL)
+		cifs_small_buf_release(smallbuf);
 
 	read_lock(&GlobalSMBSeslock);
 	if (list_empty(&server->pending_mid_q)) {
-		/* loop through server session structures attached to this and mark them dead */
+		/* loop through server session structures attached to this and
+		    mark them dead */
 		list_for_each(tmp, &GlobalSMBSessionList) {
 			ses =
 			    list_entry(tmp, struct cifsSesInfo,
@@ -424,12 +645,23 @@
 		}
 		read_unlock(&GlobalSMBSeslock);
 	} else {
+		/* although we can not zero the server struct pointer yet,
+		since there are active requests which may depnd on them,
+		mark the corresponding SMB sessions as exiting too */
+		list_for_each(tmp, &GlobalSMBSessionList) {
+			ses = list_entry(tmp, struct cifsSesInfo,
+					 cifsSessionList);
+			if (ses->server == server) {
+				ses->status = CifsExiting;
+			}
+		}
+
 		spin_lock(&GlobalMid_Lock);
 		list_for_each(tmp, &server->pending_mid_q) {
 		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 			if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
 				cFYI(1,
-					 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
+				  ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
 				task_to_wake = mid_entry->tsk;
 				if(task_to_wake) {
 					wake_up_process(task_to_wake);
@@ -438,47 +670,51 @@
 		}
 		spin_unlock(&GlobalMid_Lock);
 		read_unlock(&GlobalSMBSeslock);
-		set_current_state(TASK_INTERRUPTIBLE);
 		/* 1/8th of sec is more than enough time for them to exit */
-		schedule_timeout(HZ/8); 
+		msleep(125);
 	}
 
 	if (list_empty(&server->pending_mid_q)) {
 		/* mpx threads have not exited yet give them 
 		at least the smb send timeout time for long ops */
+		/* due to delays on oplock break requests, we need
+		to wait at least 45 seconds before giving up
+		on a request getting a response and going ahead
+		and killing cifsd */
 		cFYI(1, ("Wait for exit from demultiplex thread"));
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(46 * HZ);	
+		msleep(46000);
 		/* if threads still have not exited they are probably never
 		coming home not much else we can do but free the memory */
 	}
-	kfree(server);
 
 	write_lock(&GlobalSMBSeslock);
 	atomic_dec(&tcpSesAllocCount);
 	length = tcpSesAllocCount.counter;
+
+	/* last chance to mark ses pointers invalid
+	if there are any pointing to this (e.g
+	if a crazy root user tried to kill cifsd 
+	kernel thread explicitly this might happen) */
+	list_for_each(tmp, &GlobalSMBSessionList) {
+		ses = list_entry(tmp, struct cifsSesInfo,
+				cifsSessionList);
+		if (ses->server == server) {
+			ses->server = NULL;
+		}
+	}
 	write_unlock(&GlobalSMBSeslock);
+
+	kfree(server);
 	if(length  > 0) {
 		mempool_resize(cifs_req_poolp,
 			length + cifs_min_rcv,
 			GFP_KERNEL);
 	}
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ/4);
+	
+	msleep(250);
 	return 0;
 }
 
-static void * 
-cifs_kcalloc(size_t size, unsigned int __nocast type)
-{
-	void *addr;
-	addr = kmalloc(size, type);
-	if (addr)
-		memset(addr, 0, size);
-	return addr;
-}
-
 static int
 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
 {
@@ -495,7 +731,8 @@
 		/* does not have to be a perfect mapping since the field is
 		informational, only used for servers that do not support
 		port 445 and it can be overridden at mount time */
-		vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
+		vol->source_rfc1001_name[i] = 
+			toupper(system_utsname.nodename[i]);
 	}
 	vol->source_rfc1001_name[15] = 0;
 
@@ -570,14 +807,17 @@
 			/* NB: password legally can have multiple commas and
 			the only illegal character in a password is null */
 
-			if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
+			if ((value[temp_len] == 0) && 
+			    (value[temp_len+1] == separator[0])) {
 				/* reinsert comma */
 				value[temp_len] = separator[0];
 				temp_len+=2;  /* move after the second comma */
 				while(value[temp_len] != 0)  {
 					if (value[temp_len] == separator[0]) {
-						if (value[temp_len+1] == separator[0]) {
-							temp_len++; /* skip second comma */
+						if (value[temp_len+1] == 
+						     separator[0]) {
+						/* skip second comma */
+							temp_len++;
 						} else { 
 						/* single comma indicating start
 							 of next parm */
@@ -596,17 +836,26 @@
 				/* go from value to value + temp_len condensing 
 				double commas to singles. Note that this ends up
 				allocating a few bytes too many, which is ok */
-				vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
+				vol->password = kcalloc(1, temp_len, GFP_KERNEL);
+				if(vol->password == NULL) {
+					printk("CIFS: no memory for pass\n");
+					return 1;
+				}
 				for(i=0,j=0;i<temp_len;i++,j++) {
 					vol->password[j] = value[i];
-					if(value[i] == separator[0] && value[i+1] == separator[0]) {
+					if(value[i] == separator[0]
+						&& value[i+1] == separator[0]) {
 						/* skip second comma */
 						i++;
 					}
 				}
 				vol->password[j] = 0;
 			} else {
-				vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
+				vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
+				if(vol->password == NULL) {
+					printk("CIFS: no memory for pass\n");
+					return 1;
+				}
 				strcpy(vol->password, value);
 			}
 		} else if (strnicmp(data, "ip", 2) == 0) {
@@ -770,6 +1019,10 @@
 			vol->noperm = 0;
 		} else if (strnicmp(data, "noperm", 6) == 0) {
 			vol->noperm = 1;
+		} else if (strnicmp(data, "mapchars", 8) == 0) {
+			vol->remap = 1;
+		} else if (strnicmp(data, "nomapchars", 10) == 0) {
+			vol->remap = 0;
 		} else if (strnicmp(data, "setuids", 7) == 0) {
 			vol->setuids = 1;
 		} else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -918,14 +1171,15 @@
 
 int
 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
-		    const char *old_path, const struct nls_table *nls_codepage)
+		    const char *old_path, const struct nls_table *nls_codepage,
+		    int remap)
 {
 	unsigned char *referrals = NULL;
 	unsigned int num_referrals;
 	int rc = 0;
 
 	rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, 
-			&num_referrals, &referrals);
+			&num_referrals, &referrals, remap);
 
 	/* BB Add in code to: if valid refrl, if not ip address contact
 		the helper that resolves tcp names, mount to it, try to 
@@ -940,7 +1194,8 @@
 int
 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
 			const char *old_path, const struct nls_table *nls_codepage, 
-			unsigned int *pnum_referrals, unsigned char ** preferrals)
+			unsigned int *pnum_referrals, 
+			unsigned char ** preferrals, int remap)
 {
 	char *temp_unc;
 	int rc = 0;
@@ -965,7 +1220,7 @@
 	}
 	if (rc == 0)
 		rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
-				     pnum_referrals, nls_codepage);
+				     pnum_referrals, nls_codepage, remap);
 
 	return rc;
 }
@@ -1062,7 +1317,7 @@
 		sessinit is sent but no second negprot */
 		struct rfc1002_session_packet * ses_init_buf;
 		struct smb_hdr * smb_buf;
-		ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+		ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
 		if(ses_init_buf) {
 			ses_init_buf->trailer.session_req.called_len = 32;
 			rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
@@ -1352,6 +1607,7 @@
 			} else
 				rc = 0;
 			memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
+			srvTcp->sequence_number = 0;
 		}
 	}
 
@@ -1419,6 +1675,8 @@
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
 		if(volume_info.server_ino)
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+		if(volume_info.remap)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
 		if(volume_info.no_xattr)
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
 		if(volume_info.direct_io) {
@@ -1447,11 +1705,10 @@
 				if ((strchr(volume_info.UNC + 3, '\\') == NULL)
 				    && (strchr(volume_info.UNC + 3, '/') ==
 					NULL)) {
-					rc = connect_to_dfs_path(xid,
-								 pSesInfo,
-								 "",
-								 cifs_sb->
-								 local_nls);
+					rc = connect_to_dfs_path(xid, pSesInfo,
+							"", cifs_sb->local_nls,
+							cifs_sb->mnt_cifs_flags & 
+							  CIFS_MOUNT_MAP_SPECIAL_CHR);
 					if(volume_info.UNC)
 						kfree(volume_info.UNC);
 					FreeXid(xid);
@@ -1514,10 +1771,10 @@
 		tcon->ses = pSesInfo;
 
 		/* do not care if following two calls succeed - informational only */
-		CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
-		CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
+		CIFSSMBQFSDeviceInfo(xid, tcon);
+		CIFSSMBQFSAttributeInfo(xid, tcon);
 		if (tcon->ses->capabilities & CAP_UNIX) {
-			if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
+			if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
 				if(!volume_info.no_psx_acl) {
 					if(CIFS_UNIX_POSIX_ACL_CAP & 
 					   le64_to_cpu(tcon->fsUnixInfo.Capability))
@@ -1707,7 +1964,9 @@
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
-				ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+				ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
+				if(ses->serverOS == NULL)
+					goto sesssetup_nomem;
 				cifs_strfromUCS_le(ses->serverOS,
 					   (wchar_t *)bcc_ptr, len,nls_codepage);
 				bcc_ptr += 2 * (len + 1);
@@ -1717,7 +1976,9 @@
 				if (remaining_words > 0) {
 					len = UniStrnlen((wchar_t *)bcc_ptr,
 							 remaining_words-1);
-					ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
+					ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
+					if(ses->serverNOS == NULL)
+						goto sesssetup_nomem;
 					cifs_strfromUCS_le(ses->serverNOS,
 							   (wchar_t *)bcc_ptr,len,nls_codepage);
 					bcc_ptr += 2 * (len + 1);
@@ -1730,10 +1991,12 @@
 					}
 					remaining_words -= len + 1;
 					if (remaining_words > 0) {
-						len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+						len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
 						ses->serverDomain =
-						    cifs_kcalloc(2*(len+1),GFP_KERNEL);
+						    kcalloc(1, 2*(len+1),GFP_KERNEL);
+						if(ses->serverDomain == NULL)
+							goto sesssetup_nomem;
 						cifs_strfromUCS_le(ses->serverDomain,
 						     (wchar_t *)bcc_ptr,len,nls_codepage);
 						bcc_ptr += 2 * (len + 1);
@@ -1741,21 +2004,25 @@
 						ses->serverDomain[1+(2*len)] = 0;
 					} /* else no more room so create dummy domain string */
 					else
-						ses->serverDomain =
-						    cifs_kcalloc(2,
-							    GFP_KERNEL);
+						ses->serverDomain = 
+							kcalloc(1, 2, GFP_KERNEL);
 				} else {	/* no room so create dummy domain and NOS string */
+					/* if these kcallocs fail not much we
+					   can do, but better to not fail the
+					   sesssetup itself */
 					ses->serverDomain =
-					    cifs_kcalloc(2, GFP_KERNEL);
+					    kcalloc(1, 2, GFP_KERNEL);
 					ses->serverNOS =
-					    cifs_kcalloc(2, GFP_KERNEL);
+					    kcalloc(1, 2, GFP_KERNEL);
 				}
 			} else {	/* ASCII */
 				len = strnlen(bcc_ptr, 1024);
 				if (((long) bcc_ptr + len) - (long)
 				    pByteArea(smb_buffer_response)
 					    <= BCC(smb_buffer_response)) {
-					ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
+					if(ses->serverOS == NULL)
+						goto sesssetup_nomem;
 					strncpy(ses->serverOS,bcc_ptr, len);
 
 					bcc_ptr += len;
@@ -1763,14 +2030,18 @@
 					bcc_ptr++;
 
 					len = strnlen(bcc_ptr, 1024);
-					ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
+					if(ses->serverNOS == NULL)
+						goto sesssetup_nomem;
 					strncpy(ses->serverNOS, bcc_ptr, len);
 					bcc_ptr += len;
 					bcc_ptr[0] = 0;
 					bcc_ptr++;
 
 					len = strnlen(bcc_ptr, 1024);
-					ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
+					ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
+					if(ses->serverDomain == NULL)
+						goto sesssetup_nomem;
 					strncpy(ses->serverDomain, bcc_ptr, len);
 					bcc_ptr += len;
 					bcc_ptr[0] = 0;
@@ -1790,7 +2061,9 @@
 			smb_buffer_response->WordCount));
 		rc = -EIO;
 	}
-	
+sesssetup_nomem:	/* do not return an error on nomem for the info strings,
+			   since that could make reconnection harder, and
+			   reconnection might be needed to free memory */
 	if (smb_buffer)
 		cifs_buf_release(smb_buffer);
 
@@ -1967,7 +2240,7 @@
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
 					ses->serverOS =
-					    cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+					    kcalloc(1, 2 * (len + 1), GFP_KERNEL);
 					cifs_strfromUCS_le(ses->serverOS,
 							   (wchar_t *)
 							   bcc_ptr, len,
@@ -1981,7 +2254,7 @@
 								 remaining_words
 								 - 1);
 						ses->serverNOS =
-						    cifs_kcalloc(2 * (len + 1),
+						    kcalloc(1, 2 * (len + 1),
 							    GFP_KERNEL);
 						cifs_strfromUCS_le(ses->serverNOS,
 								   (wchar_t *)bcc_ptr,
@@ -1994,7 +2267,7 @@
 						if (remaining_words > 0) {
 							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
                             /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
-							ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
+							ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
 							cifs_strfromUCS_le(ses->serverDomain,
 							     (wchar_t *)bcc_ptr, 
                                  len,
@@ -2005,10 +2278,10 @@
 						} /* else no more room so create dummy domain string */
 						else
 							ses->serverDomain =
-							    cifs_kcalloc(2,GFP_KERNEL);
+							    kcalloc(1, 2,GFP_KERNEL);
 					} else {	/* no room so create dummy domain and NOS string */
-						ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
-						ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
+						ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
+						ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
 					}
 				} else {	/* ASCII */
 
@@ -2016,7 +2289,7 @@
 					if (((long) bcc_ptr + len) - (long)
 					    pByteArea(smb_buffer_response)
 					    <= BCC(smb_buffer_response)) {
-						ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
+						ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
 						strncpy(ses->serverOS, bcc_ptr, len);
 
 						bcc_ptr += len;
@@ -2024,14 +2297,14 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+						ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
 						strncpy(ses->serverNOS, bcc_ptr, len);
 						bcc_ptr += len;
 						bcc_ptr[0] = 0;
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
+						ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
 						strncpy(ses->serverDomain, bcc_ptr, len);
 						bcc_ptr += len;
 						bcc_ptr[0] = 0;
@@ -2281,7 +2554,7 @@
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
 					ses->serverOS =
-					    cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+					    kcalloc(1, 2 * (len + 1), GFP_KERNEL);
 					cifs_strfromUCS_le(ses->serverOS,
 							   (wchar_t *)
 							   bcc_ptr, len,
@@ -2296,7 +2569,7 @@
 								 remaining_words
 								 - 1);
 						ses->serverNOS =
-						    cifs_kcalloc(2 * (len + 1),
+						    kcalloc(1, 2 * (len + 1),
 							    GFP_KERNEL);
 						cifs_strfromUCS_le(ses->
 								   serverNOS,
@@ -2313,7 +2586,7 @@
 							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
 							ses->serverDomain =
-							    cifs_kcalloc(2 *
+							    kcalloc(1, 2 *
 								    (len +
 								     1),
 								    GFP_KERNEL);
@@ -2339,13 +2612,13 @@
 						} /* else no more room so create dummy domain string */
 						else
 							ses->serverDomain =
-							    cifs_kcalloc(2,
+							    kcalloc(1, 2,
 								    GFP_KERNEL);
 					} else {	/* no room so create dummy domain and NOS string */
 						ses->serverDomain =
-						    cifs_kcalloc(2, GFP_KERNEL);
+						    kcalloc(1, 2, GFP_KERNEL);
 						ses->serverNOS =
-						    cifs_kcalloc(2, GFP_KERNEL);
+						    kcalloc(1, 2, GFP_KERNEL);
 					}
 				} else {	/* ASCII */
 					len = strnlen(bcc_ptr, 1024);
@@ -2353,7 +2626,7 @@
 					    pByteArea(smb_buffer_response)
 					    <= BCC(smb_buffer_response)) {
 						ses->serverOS =
-						    cifs_kcalloc(len + 1,
+						    kcalloc(1, len + 1,
 							    GFP_KERNEL);
 						strncpy(ses->serverOS,
 							bcc_ptr, len);
@@ -2364,7 +2637,7 @@
 
 						len = strnlen(bcc_ptr, 1024);
 						ses->serverNOS =
-						    cifs_kcalloc(len + 1,
+						    kcalloc(1, len + 1,
 							    GFP_KERNEL);
 						strncpy(ses->serverNOS, bcc_ptr, len);
 						bcc_ptr += len;
@@ -2373,7 +2646,7 @@
 
 						len = strnlen(bcc_ptr, 1024);
 						ses->serverDomain =
-						    cifs_kcalloc(len + 1,
+						    kcalloc(1, len + 1,
 							    GFP_KERNEL);
 						strncpy(ses->serverDomain, bcc_ptr, len);	
 						bcc_ptr += len;
@@ -2675,7 +2948,7 @@
   the end since (at least) WIN2K and Windows XP have a major bug in not null
   terminating last Unicode string in response  */
 					ses->serverOS =
-					    cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+					    kcalloc(1, 2 * (len + 1), GFP_KERNEL);
 					cifs_strfromUCS_le(ses->serverOS,
 							   (wchar_t *)
 							   bcc_ptr, len,
@@ -2690,7 +2963,7 @@
 								 remaining_words
 								 - 1);
 						ses->serverNOS =
-						    cifs_kcalloc(2 * (len + 1),
+						    kcalloc(1, 2 * (len + 1),
 							    GFP_KERNEL);
 						cifs_strfromUCS_le(ses->
 								   serverNOS,
@@ -2706,7 +2979,7 @@
 							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
      /* last string not always null terminated (e.g. for Windows XP & 2000) */
 							ses->serverDomain =
-							    cifs_kcalloc(2 *
+							    kcalloc(1, 2 *
 								    (len +
 								     1),
 								    GFP_KERNEL);
@@ -2731,17 +3004,17 @@
 							    = 0;
 						} /* else no more room so create dummy domain string */
 						else
-							ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
+							ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
 					} else {  /* no room so create dummy domain and NOS string */
-						ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
-						ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
+						ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
+						ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
 					}
 				} else {	/* ASCII */
 					len = strnlen(bcc_ptr, 1024);
 					if (((long) bcc_ptr + len) - 
                         (long) pByteArea(smb_buffer_response) 
                             <= BCC(smb_buffer_response)) {
-						ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+						ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
 						strncpy(ses->serverOS,bcc_ptr, len);
 
 						bcc_ptr += len;
@@ -2749,14 +3022,14 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
+						ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
 						strncpy(ses->serverNOS, bcc_ptr, len);	
 						bcc_ptr += len;
 						bcc_ptr[0] = 0;
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
+						ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
 						strncpy(ses->serverDomain, bcc_ptr, len);
 						bcc_ptr += len;
 						bcc_ptr[0] = 0;
@@ -2868,7 +3141,7 @@
 				if(tcon->nativeFileSystem)
 					kfree(tcon->nativeFileSystem);
 				tcon->nativeFileSystem =
-				    cifs_kcalloc(length + 2, GFP_KERNEL);
+				    kcalloc(1, length + 2, GFP_KERNEL);
 				cifs_strfromUCS_le(tcon->nativeFileSystem,
 						   (wchar_t *) bcc_ptr,
 						   length, nls_codepage);
@@ -2886,7 +3159,7 @@
 				if(tcon->nativeFileSystem)
 					kfree(tcon->nativeFileSystem);
 				tcon->nativeFileSystem =
-				    cifs_kcalloc(length + 1, GFP_KERNEL);
+				    kcalloc(1, length + 1, GFP_KERNEL);
 				strncpy(tcon->nativeFileSystem, bcc_ptr,
 					length);
 			}
@@ -2959,6 +3232,7 @@
 	int rc = 0;
 	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
 	int ntlmv2_flag = FALSE;
+	int first_time = 0;
 
 	/* what if server changes its buffer size after dropping the session? */
 	if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
@@ -2977,12 +3251,13 @@
 			spin_unlock(&GlobalMid_Lock);
 
 		}
+		first_time = 1;
 	}
 	if (!rc) {
 		pSesInfo->capabilities = pSesInfo->server->capabilities;
 		if(linuxExtEnabled == 0)
 			pSesInfo->capabilities &= (~CAP_UNIX);
-		pSesInfo->sequence_number = 0;
+	/*	pSesInfo->sequence_number = 0;*/
 		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
 			pSesInfo->server->secMode,
 			pSesInfo->server->capabilities,
@@ -3015,7 +3290,10 @@
 						v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
 					if(v2_response) {
 						CalcNTLMv2_response(pSesInfo,v2_response);
-/*						cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
+				/*		if(first_time)
+							cifs_calculate_ntlmv2_mac_key(
+							  pSesInfo->server->mac_signing_key, 
+							  response, ntlm_session_key, */
 						kfree(v2_response);
 					/* BB Put dummy sig in SessSetup PDU? */
 					} else {
@@ -3028,9 +3306,11 @@
 						pSesInfo->server->cryptKey,
 						ntlm_session_key);
 
-					cifs_calculate_mac_key(pSesInfo->mac_signing_key,
-						ntlm_session_key,
-						pSesInfo->password);
+					if(first_time)
+						cifs_calculate_mac_key(
+							pSesInfo->server->mac_signing_key,
+							ntlm_session_key,
+							pSesInfo->password);
 				}
 			/* for better security the weaker lanman hash not sent
 			   in AuthSessSetup so we no longer calculate it */
@@ -3046,8 +3326,11 @@
 				pSesInfo->server->cryptKey,
 				ntlm_session_key);
 
-			cifs_calculate_mac_key(pSesInfo->mac_signing_key, 
-				ntlm_session_key, pSesInfo->password);
+			if(first_time) 		
+				cifs_calculate_mac_key(
+					pSesInfo->server->mac_signing_key,
+					ntlm_session_key, pSesInfo->password);
+
 			rc = CIFSSessSetup(xid, pSesInfo,
 				ntlm_session_key, nls_info);
 		}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f54e186..e3137aa 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -101,68 +101,15 @@
 	return full_path;
 }
 
-/* Note: caller must free return buffer */
-char *
-build_wildcard_path_from_dentry(struct dentry *direntry)
+/* char * build_wildcard_path_from_dentry(struct dentry *direntry)
 {
-	struct dentry *temp;
-	int namelen = 0;
-	char *full_path;
-
-	if(direntry == NULL)
-		return NULL;  /* not much we can do if dentry is freed and
-		we need to reopen the file after it was closed implicitly
-		when the server crashed */
-
-cifs_bwp_rename_retry:
-	for (temp = direntry; !IS_ROOT(temp);) {
-		namelen += (1 + temp->d_name.len);
-		temp = temp->d_parent;
-		if(temp == NULL) {
-			cERROR(1,("corrupt dentry"));
-			return NULL;
-		}
-	}
-
-	full_path = kmalloc(namelen+3, GFP_KERNEL);
 	if(full_path == NULL)
 		return full_path;
 
 	full_path[namelen] = '\\';
 	full_path[namelen+1] = '*';
-	full_path[namelen+2] = 0;  /* trailing null */
-
-	for (temp = direntry; !IS_ROOT(temp);) {
-		namelen -= 1 + temp->d_name.len;
-		if (namelen < 0) {
-			break;
-		} else {
-			full_path[namelen] = '\\';
-			strncpy(full_path + namelen + 1, temp->d_name.name,
-				temp->d_name.len);
-			cFYI(0, (" name: %s ", full_path + namelen));
-		}
-		temp = temp->d_parent;
-		if(temp == NULL) {
-			cERROR(1,("corrupt dentry"));
-			kfree(full_path);
-			return NULL;
-		}
-	}
-	if (namelen != 0) {
-		cERROR(1,
-		       ("We did not end path lookup where we expected namelen is %d",
-			namelen));
-		/* presumably this is only possible if we were racing with a rename 
-		of one of the parent directories  (we can not lock the dentries
-		above us to prevent this, but retrying should be harmless) */
-		kfree(full_path);
-		namelen = 0;
-		goto cifs_bwp_rename_retry;
-	}
-
-	return full_path;
-}
+	full_path[namelen+2] = 0;
+BB remove above eight lines BB */
 
 /* Inode operations in similar order to how they appear in the Linux file fs.h */
 
@@ -235,7 +182,8 @@
 
 	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
 			 desiredAccess, CREATE_NOT_DIR,
-			 &fileHandle, &oplock, buf, cifs_sb->local_nls);
+			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
 		cFYI(1, ("cifs_create returned 0x%x ", rc));
 	} else {
@@ -248,13 +196,17 @@
 					(__u64)current->euid,
 					(__u64)current->egid,
 					0 /* dev */,
-					cifs_sb->local_nls);
+					cifs_sb->local_nls, 
+					cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			} else {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
 					(__u64)-1,
 					(__u64)-1,
 					0 /* dev */,
-					cifs_sb->local_nls);
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			}
 		else {
 			/* BB implement via Windows security descriptors */
@@ -284,51 +236,48 @@
 			/* mknod case - do not leave file open */
 			CIFSSMBClose(xid, pTcon, fileHandle);
 		} else if(newinode) {
-			pCifsFile = (struct cifsFileInfo *)
+			pCifsFile =
 			   kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
-		
-			if (pCifsFile) {
-				memset((char *)pCifsFile, 0,
-				       sizeof (struct cifsFileInfo));
-				pCifsFile->netfid = fileHandle;
-				pCifsFile->pid = current->tgid;
-				pCifsFile->pInode = newinode;
-				pCifsFile->invalidHandle = FALSE;
-				pCifsFile->closePend     = FALSE;
-				init_MUTEX(&pCifsFile->fh_sem);
-				/* put the following in at open now */
-				/* pCifsFile->pfile = file; */ 
-				write_lock(&GlobalSMBSeslock);
-				list_add(&pCifsFile->tlist,&pTcon->openFileList);
-				pCifsInode = CIFS_I(newinode);
-				if(pCifsInode) {
+			
+			if(pCifsFile == NULL)
+				goto cifs_create_out;
+			memset((char *)pCifsFile, 0,
+			       sizeof (struct cifsFileInfo));
+			pCifsFile->netfid = fileHandle;
+			pCifsFile->pid = current->tgid;
+			pCifsFile->pInode = newinode;
+			pCifsFile->invalidHandle = FALSE;
+			pCifsFile->closePend     = FALSE;
+			init_MUTEX(&pCifsFile->fh_sem);
+			/* set the following in open now 
+				pCifsFile->pfile = file; */
+			write_lock(&GlobalSMBSeslock);
+			list_add(&pCifsFile->tlist,&pTcon->openFileList);
+			pCifsInode = CIFS_I(newinode);
+			if(pCifsInode) {
 				/* if readable file instance put first in list*/
-					if (write_only == TRUE) {
-                                        	list_add_tail(&pCifsFile->flist,
-							&pCifsInode->openFileList);
-					} else {
-						list_add(&pCifsFile->flist,
-							&pCifsInode->openFileList);
-					}
-					if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-						pCifsInode->clientCanCacheAll = TRUE;
-						pCifsInode->clientCanCacheRead = TRUE;
-						cFYI(1,("Exclusive Oplock granted on inode %p",
-							newinode));
-					} else if((oplock & 0xF) == OPLOCK_READ)
-						pCifsInode->clientCanCacheRead = TRUE;
+				if (write_only == TRUE) {
+                                       	list_add_tail(&pCifsFile->flist,
+						&pCifsInode->openFileList);
+				} else {
+					list_add(&pCifsFile->flist,
+						&pCifsInode->openFileList);
 				}
-				write_unlock(&GlobalSMBSeslock);
+				if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+					pCifsInode->clientCanCacheAll = TRUE;
+					pCifsInode->clientCanCacheRead = TRUE;
+					cFYI(1,("Exclusive Oplock for inode %p",
+						newinode));
+				} else if((oplock & 0xF) == OPLOCK_READ)
+					pCifsInode->clientCanCacheRead = TRUE;
 			}
+			write_unlock(&GlobalSMBSeslock);
 		}
 	} 
-
-	if (buf)
-	    kfree(buf);
-	if (full_path)
-	    kfree(full_path);
+cifs_create_out:
+	kfree(buf);
+	kfree(full_path);
 	FreeXid(xid);
-
 	return rc;
 }
 
@@ -359,11 +308,15 @@
 		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 				mode,(__u64)current->euid,(__u64)current->egid,
-				device_number, cifs_sb->local_nls);
+				device_number, cifs_sb->local_nls,
+				cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		} else {
 			rc = CIFSSMBUnixSetPerms(xid, pTcon,
 				full_path, mode, (__u64)-1, (__u64)-1,
-				device_number, cifs_sb->local_nls);
+				device_number, cifs_sb->local_nls,
+				cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		}
 
 		if(!rc) {
@@ -375,10 +328,8 @@
 		}
 	}
 
-	if (full_path)
-		kfree(full_path);
+	kfree(full_path);
 	FreeXid(xid);
-
 	return rc;
 }
 
@@ -447,43 +398,11 @@
 		if file exists or not but no access BB */
 	}
 
-	if (full_path)
-		kfree(full_path);
+	kfree(full_path);
 	FreeXid(xid);
 	return ERR_PTR(rc);
 }
 
-int
-cifs_dir_open(struct inode *inode, struct file *file)
-{				/* NB: currently unused since searches are opened in readdir */
-	int rc = 0;
-	int xid;
-	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
-	char *full_path = NULL;
-
-	xid = GetXid();
-
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-
-	if(file->f_dentry) {
-		down(&file->f_dentry->d_sb->s_vfs_rename_sem);
-		full_path = build_wildcard_path_from_dentry(file->f_dentry);
-		up(&file->f_dentry->d_sb->s_vfs_rename_sem);
-	} else {
-		FreeXid(xid);
-		return -EIO;
-	}
-
-	cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
-
-	if (full_path)
-		kfree(full_path);
-	FreeXid(xid);
-	return rc;
-}
-
 static int
 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
 {
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 9d24c40..7d2a920 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -92,7 +92,8 @@
 		cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
 		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 
 			GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
-			&netfid, &oplock,NULL, cifs_sb->local_nls);
+			&netfid, &oplock,NULL, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 		/* BB fixme - add this handle to a notify handle list */
 		if(rc) {
 			cERROR(1,("Could not open directory for notify"));  /* BB remove BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dcab7cf..dde2d25 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -254,7 +254,8 @@
 	}
 	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
 			 CREATE_NOT_DIR, &netfid, &oplock, buf,
-			 cifs_sb->local_nls);
+			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
+				 & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
 		cFYI(1, ("cifs_open returned 0x%x ", rc));
 		goto out;
@@ -287,7 +288,9 @@
 			CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 					    inode->i_mode,
 					    (__u64)-1, (__u64)-1, 0 /* dev */,
-					    cifs_sb->local_nls);
+					    cifs_sb->local_nls,
+					    cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 		} else {
 			/* BB implement via Windows security descriptors eg
 			   CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
@@ -387,7 +390,8 @@
 	} */
 	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
 			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
-			 cifs_sb->local_nls);
+			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
 		up(&pCifsFile->fh_sem);
 		cFYI(1, ("cifs_open returned 0x%x ", rc));
@@ -465,8 +469,10 @@
 				write_lock(&file->f_owner.lock);
 			}
 		}
+		write_lock(&GlobalSMBSeslock);
 		list_del(&pSMBFile->flist);
 		list_del(&pSMBFile->tlist);
+		write_unlock(&GlobalSMBSeslock);
 		write_unlock(&file->f_owner.lock);
 		kfree(pSMBFile->search_resume_name);
 		kfree(file->private_data);
@@ -506,7 +512,8 @@
 		pTcon = cifs_sb->tcon;
 
 		cFYI(1, ("Freeing private data in close dir"));
-		if (pCFileStruct->srch_inf.endOfSearch == FALSE) {
+		if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
+		   (pCFileStruct->invalidHandle == FALSE)) {
 			pCFileStruct->invalidHandle = TRUE;
 			rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
 			cFYI(1, ("Closing uncompleted readdir with rc %d",
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index d73b0aa..6709472 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -44,7 +44,8 @@
 	cFYI(1, (" Getting info on %s ", search_path));
 	/* could have done a find first instead but this returns more info */
 	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
-				  cifs_sb->local_nls);
+				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 /*	dump_mem("\nUnixQPathInfo return data", &findData,
 		 sizeof(findData)); */
 	if (rc) {
@@ -63,7 +64,9 @@
 			strncat(tmp_path, search_path, MAX_PATHCONF);
 			rc = connect_to_dfs_path(xid, pTcon->ses,
 						 /* treename + */ tmp_path,
-						 cifs_sb->local_nls);
+						 cifs_sb->local_nls, 
+						 cifs_sb->mnt_cifs_flags & 
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 			kfree(tmp_path);
 
 			/* BB fix up inode etc. */
@@ -210,7 +213,8 @@
 		pfindData = (FILE_ALL_INFO *)buf;
 		/* could do find first instead but this returns more info */
 		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
-			      cifs_sb->local_nls);
+			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
 	}
 	/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
 	if (rc) {
@@ -230,7 +234,9 @@
 			strncat(tmp_path, search_path, MAX_PATHCONF);
 			rc = connect_to_dfs_path(xid, pTcon->ses,
 						 /* treename + */ tmp_path,
-						 cifs_sb->local_nls);
+						 cifs_sb->local_nls, 
+						 cifs_sb->mnt_cifs_flags & 
+						   CIFS_MOUNT_MAP_SPECIAL_CHR);
 			kfree(tmp_path);
 			/* BB fix up inode etc. */
 		} else if (rc) {
@@ -268,7 +274,9 @@
 
 				rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 
 					search_path, &inode_num, 
-					cifs_sb->local_nls);
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 				if(rc1) {
 					cFYI(1,("GetSrvInodeNum rc %d", rc1));
 					/* BB EOPNOSUPP disable SERVER_INUM? */
@@ -410,7 +418,8 @@
 		FreeXid(xid);
 		return -ENOMEM;
 	}
-	rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
+	rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 	if (!rc) {
 		direntry->d_inode->i_nlink--;
@@ -422,10 +431,14 @@
 
 		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
 				 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
-				 &netfid, &oplock, NULL, cifs_sb->local_nls);
+				 &netfid, &oplock, NULL, cifs_sb->local_nls,
+				 cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		if (rc==0) {
 			CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
-					      cifs_sb->local_nls);
+					      cifs_sb->local_nls, 
+					      cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			CIFSSMBClose(xid, pTcon, netfid);
 			direntry->d_inode->i_nlink--;
 		}
@@ -439,7 +452,9 @@
 			if (!(pTcon->ses->flags & CIFS_SES_NT4))
 				rc = CIFSSMBSetTimes(xid, pTcon, full_path,
 						     pinfo_buf,
-						     cifs_sb->local_nls);
+						     cifs_sb->local_nls,
+						     cifs_sb->mnt_cifs_flags & 
+							CIFS_MOUNT_MAP_SPECIAL_CHR);
 			else
 				rc = -EOPNOTSUPP;
 
@@ -461,7 +476,9 @@
 						 FILE_OPEN, SYNCHRONIZE |
 						 FILE_WRITE_ATTRIBUTES, 0,
 						 &netfid, &oplock, NULL,
-						 cifs_sb->local_nls);
+						 cifs_sb->local_nls,
+						 cifs_sb->mnt_cifs_flags & 
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 				if (rc==0) {
 					rc = CIFSSMBSetFileTimes(xid, pTcon,
 								 pinfo_buf,
@@ -472,8 +489,10 @@
 			kfree(pinfo_buf);
 		}
 		if (rc==0) {
-			rc = CIFSSMBDelFile(xid, pTcon, full_path,
-					    cifs_sb->local_nls);
+			rc = CIFSSMBDelFile(xid, pTcon, full_path, 
+					    cifs_sb->local_nls, 
+					    cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			if (!rc) {
 				direntry->d_inode->i_nlink--;
 			} else if (rc == -ETXTBSY) {
@@ -485,11 +504,15 @@
 						 CREATE_NOT_DIR |
 						 CREATE_DELETE_ON_CLOSE,
 						 &netfid, &oplock, NULL,
-						 cifs_sb->local_nls);
+						 cifs_sb->local_nls, 
+						 cifs_sb->mnt_cifs_flags & 
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 				if (rc==0) {
 					CIFSSMBRenameOpenFile(xid, pTcon,
 						netfid, NULL,
-						cifs_sb->local_nls);
+						cifs_sb->local_nls,
+						cifs_sb->mnt_cifs_flags &
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 					CIFSSMBClose(xid, pTcon, netfid);
 		                        direntry->d_inode->i_nlink--;
 				}
@@ -534,7 +557,8 @@
 		return -ENOMEM;
 	}
 	/* BB add setting the equivalent of mode via CreateX w/ACLs */
-	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
+	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
+			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
 		cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
 		d_drop(direntry);
@@ -558,12 +582,16 @@
 						    (__u64)current->euid,
 						    (__u64)current->egid,
 						    0 /* dev_t */,
-						    cifs_sb->local_nls);
+						    cifs_sb->local_nls,
+						    cifs_sb->mnt_cifs_flags &
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 			} else {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 						    mode, (__u64)-1,
 						    (__u64)-1, 0 /* dev_t */,
-						    cifs_sb->local_nls);
+						    cifs_sb->local_nls,
+						    cifs_sb->mnt_cifs_flags & 
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 			}
 		else {
 			/* BB to be implemented via Windows secrty descriptors
@@ -600,7 +628,8 @@
 		return -ENOMEM;
 	}
 
-	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
+	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
+			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 	if (!rc) {
 		inode->i_nlink--;
@@ -653,7 +682,9 @@
 	}
 
 	rc = CIFSSMBRename(xid, pTcon, fromName, toName,
-			   cifs_sb_source->local_nls);
+			   cifs_sb_source->local_nls,
+			   cifs_sb_source->mnt_cifs_flags &
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc == -EEXIST) {
 		/* check if they are the same file because rename of hardlinked
 		   files is a noop */
@@ -665,11 +696,16 @@
 		if (info_buf_source != NULL) {
 			info_buf_target = info_buf_source + 1;
 			rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
-				info_buf_source, cifs_sb_source->local_nls);
+				info_buf_source, cifs_sb_source->local_nls, 
+				cifs_sb_source->mnt_cifs_flags &
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 			if (rc == 0) {
 				rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
 						info_buf_target,
-						cifs_sb_target->local_nls);
+						cifs_sb_target->local_nls,
+						/* remap based on source sb */
+						cifs_sb_source->mnt_cifs_flags &
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 			}
 			if ((rc == 0) &&
 			    (info_buf_source->UniqueId ==
@@ -685,7 +721,9 @@
 				cifs_unlink(target_inode, target_direntry);
 				rc = CIFSSMBRename(xid, pTcon, fromName,
 						   toName,
-						   cifs_sb_source->local_nls);
+						   cifs_sb_source->local_nls,
+						   cifs_sb_source->mnt_cifs_flags
+						   & CIFS_MOUNT_MAP_SPECIAL_CHR);
 			}
 			kfree(info_buf_source);
 		} /* if we can not get memory just leave rc as EEXIST */
@@ -705,10 +743,14 @@
 		   might not right be right access to request */
 		rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
 				 CREATE_NOT_DIR, &netfid, &oplock, NULL,
-				 cifs_sb_source->local_nls);
+				 cifs_sb_source->local_nls, 
+				 cifs_sb_source->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		if (rc==0) {
 			CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
-					      cifs_sb_source->local_nls);
+					      cifs_sb_source->local_nls, 
+					      cifs_sb_source->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			CIFSSMBClose(xid, pTcon, netfid);
 		}
 	}
@@ -962,7 +1004,9 @@
 			   it by handle */
 			rc = CIFSSMBSetEOF(xid, pTcon, full_path,
 					   attrs->ia_size, FALSE,
-					   cifs_sb->local_nls);
+					   cifs_sb->local_nls, 
+					   cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
 		}
 
@@ -999,7 +1043,9 @@
 	if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
 	    && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
 		rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
-					 0 /* dev_t */, cifs_sb->local_nls);
+					 0 /* dev_t */, cifs_sb->local_nls,
+					 cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 	else if (attrs->ia_valid & ATTR_MODE) {
 		if ((mode & S_IWUGO) == 0) /* not writeable */ {
 			if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
@@ -1048,7 +1094,9 @@
 		   via Handle (SetFileInfo) instead of by path */
 		if (!(pTcon->ses->flags & CIFS_SES_NT4))
 			rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
-					     cifs_sb->local_nls);
+					     cifs_sb->local_nls,
+					     cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 		else
 			rc = -EOPNOTSUPP;
 
@@ -1063,7 +1111,9 @@
 			rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
 					 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
 					 CREATE_NOT_DIR, &netfid, &oplock,
-					 NULL, cifs_sb->local_nls);
+					 NULL, cifs_sb->local_nls,
+					 cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			if (rc==0) {
 				rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
 							 netfid);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index b4b8e20..b0ea668 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -20,30 +20,93 @@
  *   along with this library; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
+
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifs_debug.h"
+#include "cifsfs.h"
+
+#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
 
 int cifs_ioctl (struct inode * inode, struct file * filep, 
 		unsigned int command, unsigned long arg)
 {
 	int rc = -ENOTTY; /* strange error - but the precedent */
+	int xid;
+	struct cifs_sb_info *cifs_sb;
 #ifdef CONFIG_CIFS_POSIX
-	cFYI(1,("ioctl file %p  cmd %u  arg %lu",filep,command,arg));
-	switch(command) {
-		case EXT2_IOC_GETFLAGS:
-			cFYI(1,("get flags not implemented yet"));
-			return -EOPNOTSUPP;
-		case EXT2_IOC_SETFLAGS:
-			cFYI(1,("set flags not implemented yet"));
-			return -EOPNOTSUPP;
-		default:
-			cFYI(1,("unsupported ioctl"));
-			return rc;
+	__u64	ExtAttrBits = 0;
+	__u64	ExtAttrMask = 0;
+	__u64   caps;
+	struct cifsTconInfo *tcon;
+	struct cifsFileInfo *pSMBFile =
+		(struct cifsFileInfo *)filep->private_data;
+#endif /* CONFIG_CIFS_POSIX */
+
+	xid = GetXid();
+
+        cFYI(1,("ioctl file %p  cmd %u  arg %lu",filep,command,arg));
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+
+#ifdef CONFIG_CIFS_POSIX
+	tcon = cifs_sb->tcon;
+	if(tcon)
+		caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
+	else {
+		rc = -EIO;
+		FreeXid(xid);
+		return -EIO;
 	}
 #endif /* CONFIG_CIFS_POSIX */
+
+	switch(command) {
+		case CIFS_IOC_CHECKUMOUNT:
+			cFYI(1,("User unmount attempted"));
+			if(cifs_sb->mnt_uid == current->uid)
+				rc = 0;
+			else {
+				rc = -EACCES;
+				cFYI(1,("uids do not match"));
+			}
+			break;
+#ifdef CONFIG_CIFS_POSIX
+		case EXT2_IOC_GETFLAGS:
+			if(CIFS_UNIX_EXTATTR_CAP & caps) {
+				if (pSMBFile == NULL)
+					break;
+				rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
+					&ExtAttrBits, &ExtAttrMask);
+				if(rc == 0)
+					rc = put_user(ExtAttrBits &
+						EXT2_FL_USER_VISIBLE,
+						(int __user *)arg);
+			}
+			break;
+
+		case EXT2_IOC_SETFLAGS:
+			if(CIFS_UNIX_EXTATTR_CAP & caps) {
+				if(get_user(ExtAttrBits,(int __user *)arg)) {
+					rc = -EFAULT;
+					break;
+				}
+				if (pSMBFile == NULL)
+					break;
+				/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
+					extAttrBits, &ExtAttrMask);*/
+				
+			}
+			cFYI(1,("set flags not implemented yet"));
+			break;
+#endif /* CONFIG_CIFS_POSIX */
+		default:
+			cFYI(1,("unsupported ioctl"));
+			break;
+	}
+
+	FreeXid(xid);
 	return rc;
 } 
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 1455810..bde0fab 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -59,10 +59,14 @@
 
 	if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
 		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
-					    cifs_sb_target->local_nls);
+					    cifs_sb_target->local_nls, 
+					    cifs_sb_target->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 	else {
 		rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
-					cifs_sb_target->local_nls);
+					cifs_sb_target->local_nls, 
+					cifs_sb_target->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 		if(rc == -EIO)
 			rc = -EOPNOTSUPP;  
 	}
@@ -260,7 +264,10 @@
 				cifs_sb->local_nls);
 	else {
 		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
-				OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
+				OPEN_REPARSE_POINT,&fid, &oplock, NULL, 
+				cifs_sb->local_nls, 
+				cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 		if(!rc) {
 			rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
 				tmpbuffer,
@@ -279,7 +286,10 @@
 					strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
 					strncat(tmp_path, full_path, MAX_PATHCONF);
 					rc = get_dfs_path(xid, pTcon->ses, tmp_path,
-						cifs_sb->local_nls, &num_referrals, &referrals);
+						cifs_sb->local_nls,
+						&num_referrals, &referrals,
+						cifs_sb->mnt_cifs_flags &
+						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 					cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
 					if((num_referrals == 0) && (rc == 0))
 						rc = -EACCES;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 7b38d30..db14b50 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -28,6 +28,7 @@
 #include "cifs_debug.h"
 #include "smberr.h"
 #include "nterr.h"
+#include "cifs_unicode.h"
 
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
@@ -451,25 +452,30 @@
 			atomic_inc(&tcon->num_oplock_brks);
 #endif
 			list_for_each(tmp1,&tcon->openFileList){
-				netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
+				netfile = list_entry(tmp1,struct cifsFileInfo,
+						     tlist);
 				if(pSMB->Fid == netfile->netfid) {
 					struct cifsInodeInfo *pCifsInode;
 					read_unlock(&GlobalSMBSeslock);
-					cFYI(1,("Matching file id, processing oplock break"));
+					cFYI(1,("file id match, oplock break"));
 					pCifsInode = 
 						CIFS_I(netfile->pInode);
 					pCifsInode->clientCanCacheAll = FALSE;
 					if(pSMB->OplockLevel == 0)
-						pCifsInode->clientCanCacheRead = FALSE;
+						pCifsInode->clientCanCacheRead
+							= FALSE;
 					pCifsInode->oplockPending = TRUE;
-					AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
+					AllocOplockQEntry(netfile->pInode,
+							  netfile->netfid,
+							  tcon);
 					cFYI(1,("about to wake up oplock thd"));
-					wake_up_process(oplockThread);               
+					if(oplockThread)
+					    wake_up_process(oplockThread);
 					return TRUE;
 				}
 			}
 			read_unlock(&GlobalSMBSeslock);
-			cFYI(1,("No matching file for oplock break on connection"));
+			cFYI(1,("No matching file for oplock break"));
 			return TRUE;
 		}
 	}
@@ -490,7 +496,7 @@
 
 	buffer = (unsigned char *) smb_buf;
 	for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
-		if (i % 8 == 0) {	/* we have reached the beginning of line  */
+		if (i % 8 == 0) {	/* have reached the beginning of line */
 			printk(KERN_DEBUG "| ");
 			j = 0;
 		}
@@ -501,7 +507,7 @@
 		else
 			debug_line[1 + (2 * j)] = '_';
 
-		if (i % 8 == 7) {	/* we have reached end of line, time to print ascii */
+		if (i % 8 == 7) { /* reached end of line, time to print ascii */
 			debug_line[16] = 0;
 			printk(" | %s\n", debug_line);
 		}
@@ -514,3 +520,141 @@
 	printk( " | %s\n", debug_line);
 	return;
 }
+
+/* Windows maps these to the user defined 16 bit Unicode range since they are
+   reserved symbols (along with \ and /), otherwise illegal to store
+   in filenames in NTFS */
+#define UNI_ASTERIK     (__u16) ('*' + 0xF000)
+#define UNI_QUESTION    (__u16) ('?' + 0xF000)
+#define UNI_COLON       (__u16) (':' + 0xF000)
+#define UNI_GRTRTHAN    (__u16) ('>' + 0xF000)
+#define UNI_LESSTHAN    (__u16) ('<' + 0xF000)
+#define UNI_PIPE        (__u16) ('|' + 0xF000)
+#define UNI_SLASH       (__u16) ('\\' + 0xF000)
+
+/* Convert 16 bit Unicode pathname from wire format to string in current code
+   page.  Conversion may involve remapping up the seven characters that are
+   only legal in POSIX-like OS (if they are present in the string). Path
+   names are little endian 16 bit Unicode on the wire */
+int
+cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
+		    const struct nls_table * cp)
+{
+	int i,j,len;
+	__u16 src_char;
+
+	for(i = 0, j = 0; i < maxlen; i++) {
+		src_char = le16_to_cpu(source[i]);
+		switch (src_char) {
+			case 0:
+				goto cUCS_out; /* BB check this BB */
+			case UNI_COLON:
+				target[j] = ':';
+				break;
+			case UNI_ASTERIK:
+				target[j] = '*';
+				break;
+			case UNI_QUESTION:
+				target[j] = '?';
+				break;
+			/* BB We can not handle remapping slash until
+			   all the calls to build_path_from_dentry
+			   are modified, as they use slash as separator BB */
+			/* case UNI_SLASH:
+				target[j] = '\\';
+				break;*/
+			case UNI_PIPE:
+				target[j] = '|';
+				break;
+			case UNI_GRTRTHAN:
+				target[j] = '>';
+				break;
+			case UNI_LESSTHAN:
+				target[j] = '<';
+			default: 
+				len = cp->uni2char(src_char, &target[j], 
+						NLS_MAX_CHARSET_SIZE);
+				if(len > 0) {
+					j += len;
+					continue;
+				} else {
+					target[j] = '?';
+				}
+		}
+		j++;
+		/* make sure we do not overrun callers allocated temp buffer */
+		if(j >= (2 * NAME_MAX))
+			break;
+	}
+cUCS_out:
+	target[j] = 0;
+	return j;
+}
+
+/* Convert 16 bit Unicode pathname to wire format from string in current code
+   page.  Conversion may involve remapping up the seven characters that are
+   only legal in POSIX-like OS (if they are present in the string). Path
+   names are little endian 16 bit Unicode on the wire */
+int
+cifsConvertToUCS(__le16 * target, const char *source, int maxlen, 
+		 const struct nls_table * cp, int mapChars)
+{
+	int i,j,charlen;
+	int len_remaining = maxlen;
+	char src_char;
+
+	if(!mapChars) 
+		return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
+
+	for(i = 0, j = 0; i < maxlen; j++) {
+		src_char = source[i];
+		switch (src_char) {
+			case 0:
+				goto ctoUCS_out;
+			case ':':
+				target[j] = cpu_to_le16(UNI_COLON);
+				break;
+			case '*':
+				target[j] = cpu_to_le16(UNI_ASTERIK);
+				break;
+			case '?':
+				target[j] = cpu_to_le16(UNI_QUESTION);
+				break;
+			case '<':
+				target[j] = cpu_to_le16(UNI_LESSTHAN);
+				break;
+			case '>':
+				target[j] = cpu_to_le16(UNI_GRTRTHAN);
+				break;
+			case '|':
+				target[j] = cpu_to_le16(UNI_PIPE);
+				break;			
+			/* BB We can not handle remapping slash until
+			   all the calls to build_path_from_dentry
+			   are modified, as they use slash as separator BB */
+			/* case '\\':
+				target[j] = cpu_to_le16(UNI_SLASH);
+				break;*/
+			default:
+				charlen = cp->char2uni(source+i,
+					len_remaining, target+j);
+				/* if no match, use question mark, which
+				at least in some cases servers as wild card */
+				if(charlen < 1) {
+					target[j] = cpu_to_le16(0x003f);
+					charlen = 1;
+				}
+				len_remaining -= charlen;
+				/* character may take more than one byte in the
+				   the source string, but will take exactly two
+				   bytes in the target string */
+				i+= charlen;
+				continue;
+		}
+		i++; /* move to next char in source string */
+		len_remaining--;
+	}
+
+ctoUCS_out:
+	return i;
+}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 4e34c89..a92af41 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -78,6 +78,7 @@
 	{ErrQuota, -EDQUOT},
 	{ErrNotALink, -ENOLINK},
 	{ERRnetlogonNotStarted,-ENOPROTOOPT},
+	{ErrTooManyLinks,-EMLINK},
 	{0, 0}
 };
 
@@ -206,7 +207,7 @@
 	{
 	ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
 	ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
-	ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
+	ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, {
 	ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
 	ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
 	ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
@@ -742,7 +743,7 @@
 	ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
 	ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
 	ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
-	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
+	ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, {
 	ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
 	ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
 	ERRDOS, 21, 0xc000026e}, {
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index f8bea39..2255771 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -3,7 +3,7 @@
  *
  *   Directory search handling
  * 
- *   Copyright (C) International Business Machines  Corp., 2004
+ *   Copyright (C) International Business Machines  Corp., 2004, 2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -65,14 +65,14 @@
 	struct cifsTconInfo *pTcon;
 	int rc = 0;
 
-	cFYI(1, ("For %s ", qstring->name));
+	cFYI(1, ("For %s", qstring->name));
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
 
 	qstring->hash = full_name_hash(qstring->name, qstring->len);
 	tmp_dentry = d_lookup(file->f_dentry, qstring);
 	if (tmp_dentry) {
-		cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
+		cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
 		*ptmp_inode = tmp_dentry->d_inode;
 /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
 		if(*ptmp_inode == NULL) {
@@ -105,8 +105,11 @@
 }
 
 static void fill_in_inode(struct inode *tmp_inode,
-	FILE_DIRECTORY_INFO *pfindData, int *pobject_type)
+	FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode)
 {
+	loff_t local_size;
+	struct timespec local_mtime;
+
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
 	__u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
@@ -116,6 +119,10 @@
 	cifsInfo->cifsAttrs = attr;
 	cifsInfo->time = jiffies;
 
+	/* save mtime and size */
+	local_mtime = tmp_inode->i_mtime;
+	local_size  = tmp_inode->i_size;
+
 	/* Linux can not store file creation time unfortunately so ignore it */
 	tmp_inode->i_atime =
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
@@ -134,7 +141,6 @@
 		tmp_inode->i_mode = cifs_sb->mnt_file_mode;
 	}
 
-	cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
 	if (attr & ATTR_DIRECTORY) {
 		*pobject_type = DT_DIR;
 		/* override default perms since we do not lock dirs */
@@ -175,30 +181,46 @@
 	      (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
 	      tmp_inode->i_blksize));
 	if (S_ISREG(tmp_inode->i_mode)) {
-		cFYI(1, (" File inode "));
+		cFYI(1, ("File inode"));
 		tmp_inode->i_op = &cifs_file_inode_ops;
 		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
 			tmp_inode->i_fop = &cifs_file_direct_ops;
 		else
 			tmp_inode->i_fop = &cifs_file_ops;
 		tmp_inode->i_data.a_ops = &cifs_addr_ops;
+
+		if(isNewInode)
+			return; /* No sense invalidating pages for new inode since we
+					   have not started caching readahead file data yet */
+
+		if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+			(local_size == tmp_inode->i_size)) {
+			cFYI(1, ("inode exists but unchanged"));
+		} else {
+			/* file may have changed on server */
+			cFYI(1, ("invalidate inode, readdir detected change"));
+			invalidate_remote_inode(tmp_inode);
+		}
 	} else if (S_ISDIR(tmp_inode->i_mode)) {
-		cFYI(1, (" Directory inode"));
+		cFYI(1, ("Directory inode"));
 		tmp_inode->i_op = &cifs_dir_inode_ops;
 		tmp_inode->i_fop = &cifs_dir_ops;
 	} else if (S_ISLNK(tmp_inode->i_mode)) {
-		cFYI(1, (" Symbolic Link inode "));
+		cFYI(1, ("Symbolic Link inode"));
 		tmp_inode->i_op = &cifs_symlink_inode_ops;
 	} else {
-		cFYI(1, (" Init special inode "));
+		cFYI(1, ("Init special inode"));
 		init_special_inode(tmp_inode, tmp_inode->i_mode,
 				   tmp_inode->i_rdev);
 	}
 }
 
 static void unix_fill_in_inode(struct inode *tmp_inode,
-	FILE_UNIX_INFO *pfindData, int *pobject_type)
+	FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
 {
+	loff_t local_size;
+	struct timespec local_mtime;
+
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
 
@@ -208,6 +230,10 @@
 	cifsInfo->time = jiffies;
 	atomic_inc(&cifsInfo->inUse);
 
+	/* save mtime and size */
+	local_mtime = tmp_inode->i_mtime;
+	local_size  = tmp_inode->i_size;
+
 	tmp_inode->i_atime =
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
 	tmp_inode->i_mtime =
@@ -265,6 +291,19 @@
 		else
 			tmp_inode->i_fop = &cifs_file_ops;
 		tmp_inode->i_data.a_ops = &cifs_addr_ops;
+
+		if(isNewInode)
+			return; /* No sense invalidating pages for new inode since we
+					   have not started caching readahead file data yet */
+
+		if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+			(local_size == tmp_inode->i_size)) {
+			cFYI(1, ("inode exists but unchanged"));
+		} else {
+			/* file may have changed on server */
+			cFYI(1, ("invalidate inode, readdir detected change"));
+			invalidate_remote_inode(tmp_inode);
+		}
 	} else if (S_ISDIR(tmp_inode->i_mode)) {
 		cFYI(1, ("Directory inode"));
 		tmp_inode->i_op = &cifs_dir_inode_ops;
@@ -314,15 +353,16 @@
 		return -EINVAL;
 
 	down(&file->f_dentry->d_sb->s_vfs_rename_sem);
-	full_path = build_wildcard_path_from_dentry(file->f_dentry);
+	full_path = build_path_from_dentry(file->f_dentry);
 	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
 
 	if(full_path == NULL) {
 		return -ENOMEM;
 	}
 
-	cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
+	cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos));
 
+ffirst_retry:
 	/* test for Unix extensions */
 	if (pTcon->ses->capabilities & CAP_UNIX) {
 		cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 
@@ -332,10 +372,16 @@
 		cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
 	}
 
-	rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 
-		&cifsFile->netfid, &cifsFile->srch_inf); 
+	rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
+		&cifsFile->netfid, &cifsFile->srch_inf,
+		cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if(rc == 0)
 		cifsFile->invalidHandle = FALSE;
+	if((rc == -EOPNOTSUPP) && 
+		(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
+		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
+		goto ffirst_retry;
+	}
 	kfree(full_path);
 	return rc;
 }
@@ -363,10 +409,15 @@
 	cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
 	/* validate that new_entry is not past end of SMB */
 	if(new_entry >= end_of_smb) {
-		cFYI(1,("search entry %p began after end of SMB %p old entry %p",
-			new_entry,end_of_smb,old_entry)); 
+		cERROR(1,
+		      ("search entry %p began after end of SMB %p old entry %p",
+			new_entry, end_of_smb, old_entry)); 
 		return NULL;
-	} else
+	} else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) {
+		cERROR(1,("search entry %p extends after end of SMB %p",
+			new_entry, end_of_smb));
+		return NULL;
+	} else 
 		return new_entry;
 
 }
@@ -594,7 +645,12 @@
 	if(unicode) {
 		/* BB fixme - test with long names */
 		/* Note converted filename can be longer than in unicode */
-		pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt);
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
+			pqst->len = cifs_convertUCSpath((char *)pqst->name,
+					(__le16 *)filename, len/2, nlt);
+		else
+			pqst->len = cifs_strfromUCS_le((char *)pqst->name,
+					(wchar_t *)filename,len/2,nlt);
 	} else {
 		pqst->name = filename;
 		pqst->len = len;
@@ -654,10 +710,15 @@
 		insert_inode_hash(tmp_inode);
 	}
 
+	/* we pass in rc below, indicating whether it is a new inode,
+	   so we can figure out whether to invalidate the inode cached
+	   data if the file has changed */
 	if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
-		unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type);
+		unix_fill_in_inode(tmp_inode,
+				   (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc);
 	} else {
-		fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type);
+		fill_in_inode(tmp_inode,
+			      (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
 	}
 	
 	rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
@@ -823,7 +884,11 @@
 		end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
 			smbCalcSize((struct smb_hdr *)
 				    cifsFile->srch_inf.ntwrk_buf_start);
-		tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL);
+		/* To be safe - for UCS to UTF-8 with strings loaded
+		with the rare long characters alloc more to account for
+		such multibyte target UTF-8 characters. cifs_unicode.c,
+		which actually does the conversion, has the same limit */
+		tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
 		for(i=0;(i<num_to_fill) && (rc == 0);i++) {
 			if(current_entry == NULL) {
 				/* evaluate whether this case is an error */
@@ -832,19 +897,6 @@
 				break;
 			}
 
-			/* BB FIXME - need to enable the below code BB */
-
-		/* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
-			   (cifsFile->srch_inf.info_level != 
-				   something that supports server inodes)) {
-				create dentry
-				create inode
-				fill in inode new_inode (getting local i_ino)
-			}
-			also create local inode for performance reasons (so we 
-			have a cache of inode metadata) unless this new mount 
-			parm says otherwise */
-
 			rc = cifs_filldir(current_entry, file, 
 					filldir, direntry,tmp_buf);
 			file->f_pos++;
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index e21f138..cd41c67 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -22,94 +22,159 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
  */
 
-#define SUCCESS 0		/* The request was successful. */
-#define ERRDOS 0x01		/* Error is from the core DOS operating system set */
-#define ERRSRV 0x02		/* Error is generated by the file server daemon */
-#define ERRHRD 0x03		/* Error is a hardware error. */
-#define ERRCMD 0xFF		/*  Command was not in the "SMB" format. */
+#define SUCCESS	0x00	/* The request was successful. */
+#define ERRDOS	0x01	/* Error is from the core DOS operating system set */
+#define ERRSRV	0x02	/* Error is generated by the file server daemon */
+#define ERRHRD	0x03	/* Error is a hardware error. */
+#define ERRCMD	0xFF	/* Command was not in the "SMB" format. */
 
 /* The following error codes may be generated with the SUCCESS error class.*/
 
-#define SUCCESS 0		/* The request was successful. */
+/*#define SUCCESS	0	The request was successful. */
 
 /* The following error codes may be generated with the ERRDOS error class.*/
 
-#define ERRbadfunc 1		/* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */
-#define ERRbadfile 2		/*File not found. The last component of a file's pathname could not be found. */
-#define ERRbadpath 3		/* Directory invalid. A directory component in a pathname could not be found. */
-#define ERRnofids 4		/* Too many open files. The server has no file handles available. */
-#define ERRnoaccess 5		/* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */
-#define ERRbadfid 6		/* Invalid file handle. The file handle specified was not recognized by the server. */
-#define ERRbadmcb 7		/* Memory control blocks destroyed. */
-#define ERRnomem 8		/* Insufficient server memory to perform the requested function. */
-#define ERRbadmem 9		/* Invalid memory block address. */
-#define ERRbadenv 10		/* Invalid environment. */
-#define ERRbadformat 11		/* Invalid format. */
-#define ERRbadaccess 12		/* Invalid open mode. */
-#define ERRbaddata 13		/* Invalid data (generated only by IOCTL calls within the server). */
-#define ERRbaddrive 15		/* Invalid drive specified. */
-#define ERRremcd 16		/* A Delete Directory request attempted to remove the server's current directory. */
-#define ERRdiffdevice 17	/* Not same device (e.g., a cross volume rename was attempted */
-#define ERRnofiles 18		/* A File Search command can find no more files matching the specified criteria. */
-#define ERRgeneral 31
-#define ERRbadshare 32		/* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
-#define ERRlock 33		/* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */
-#define ERRunsup     50
-#define ERRnosuchshare 67
-#define ERRfilexists 80		/* The file named in the request already exists. */
-#define ERRinvparm   87
-#define ERRdiskfull  112
-#define ERRinvname   123
-#define ERRinvlevel  124
-#define ERRdirnotempty 145
-#define ERRnotlocked   158
-#define ERRalreadyexists 183
-#define ERRbadpipe 230
-#define ERRpipebusy 231
-#define ERRpipeclosing 232
-#define ERRnotconnected 233
-#define ERRmoredata    234
-#define ERReasnotsupported 282
-#define ErrQuota 0x200		/* The operation would cause a quota limit to be exceeded. */
-#define ErrNotALink 0x201	/* A link operation was performed on a pathname that
-				   was not a link. */
+#define ERRbadfunc		1	/* Invalid function. The server did not
+					   recognize or could not perform a
+					   system call generated by the server,
+					   e.g., set the DIRECTORY attribute on
+					   a data file, invalid seek mode. */
+#define ERRbadfile		2	/* File not found. The last component
+					   of a file's pathname could not be
+					   found. */
+#define ERRbadpath		3	/* Directory invalid. A directory
+					   component in a pathname could not be
+					   found. */
+#define ERRnofids		4	/* Too many open files. The server has
+					   no file handles available. */
+#define ERRnoaccess		5	/* Access denied, the client's context
+					   does not permit the requested
+					   function. This includes the
+					   following conditions: invalid rename
+					   command, write to Fid open for read
+					   only, read on Fid open for write
+					   only, attempt to delete a non-empty
+					   directory */
+#define ERRbadfid		6	/* Invalid file handle. The file handle
+					   specified was not recognized by the
+					   server. */
+#define ERRbadmcb		7	/* Memory control blocks destroyed. */
+#define ERRnomem		8	/* Insufficient server memory to
+					   perform the requested function. */
+#define ERRbadmem		9	/* Invalid memory block address. */
+#define ERRbadenv		10	/* Invalid environment. */
+#define ERRbadformat		11	/* Invalid format. */
+#define ERRbadaccess		12	/* Invalid open mode. */
+#define ERRbaddata		13	/* Invalid data (generated only by
+					   IOCTL calls within the server). */
+#define ERRbaddrive		15	/* Invalid drive specified. */
+#define ERRremcd		16	/* A Delete Directory request attempted
+					   to remove the server's current
+					   directory. */
+#define ERRdiffdevice		17	/* Not same device (e.g., a cross
+					   volume rename was attempted */
+#define ERRnofiles		18	/* A File Search command can find no
+					   more files matching the specified
+					   criteria. */
+#define ERRgeneral		31
+#define ERRbadshare		32	/* The sharing mode specified for an
+					   Open conflicts with existing FIDs on
+					   the file. */
+#define ERRlock			33	/* A Lock request conflicted with an
+					   existing lock or specified an
+					   invalid mode, or an Unlock requested
+					   attempted to remove a lock held by
+					   another process. */
+#define ERRunsup		50
+#define ERRnosuchshare		67
+#define ERRfilexists		80	/* The file named in the request
+					   already exists. */
+#define ERRinvparm		87
+#define ERRdiskfull		112
+#define ERRinvname		123
+#define ERRinvlevel		124
+#define ERRdirnotempty		145
+#define ERRnotlocked		158
+#define ERRalreadyexists	183
+#define ERRbadpipe		230
+#define ERRpipebusy		231
+#define ERRpipeclosing		232
+#define ERRnotconnected		233
+#define ERRmoredata		234
+#define ERReasnotsupported	282
+#define ErrQuota		0x200	/* The operation would cause a quota
+					   limit to be exceeded. */
+#define ErrNotALink		0x201	/* A link operation was performed on a
+					   pathname that was not a link. */
 
-/* Following error codes may be generated with the ERRSRV error
-class.*/
+/* Below errors are used internally (do not come over the wire) for passthrough
+   from STATUS codes to POSIX only  */
+#define ErrTooManyLinks         0xFFFE   
 
-#define ERRerror 1		/* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */
-#define ERRbadpw 2		/* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
-#define ERRbadtype 3		/* used for indicating DFS referral needed */
-#define ERRaccess 4		/* The client does not have the necessary access rights within the specified context for requested function. */
-#define ERRinvtid 5		/* The Tid specified in a command was invalid. */
-#define ERRinvnetname 6		/* Invalid network name in tree connect. */
-#define ERRinvdevice 7		/* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
-#define ERRqfull 49		/* Print queue full (files) -- returned by open print file. */
-#define ERRqtoobig 50		/* Print queue full -- no space. */
-#define ERRqeof         51	/* EOF on print queue dump */
-#define ERRinvpfid      52	/* Invalid print file FID. */
-#define ERRsmbcmd       64	/* The server did not recognize the command received. */
-#define ERRsrverror     65	/* The server encountered an internal error, e.g., system file unavailable. */
-#define ERRbadBID       66	/* (obsolete) */
-#define ERRfilespecs    67	/* The Fid and pathname parameters contained an invalid combination of values. */
-#define ERRbadLink      68	/* (obsolete) */
-#define ERRbadpermits   69	/* The access permissions specified for a file or directory are not a valid combination. */
-#define ERRbadPID       70
-#define ERRsetattrmode  71	/* attribute (mode) is invalid */
-#define ERRpaused       81	/* Server is paused */
-#define ERRmsgoff	82	/* reserved - messaging off */
-#define ERRnoroom       83	/* reserved - no room for message */
-#define ERRrmuns        87	/* reserved - too many remote names */
-#define ERRtimeout      88	/* operation timed out */
-#define ERRnoresource   89	/* No resources available for request */
-#define ERRtoomanyuids  90	/* Too many UIDs active on this session */
-#define ERRbaduid       91	/* The UID is not known as a valid user */
-#define ERRusempx      250	/* temporarily unable to use raw */
-#define ERRusestd      251	/* temporarily unable to use either raw or mpx */
-#define ERR_NOTIFY_ENUM_DIR 1024
-#define ERRaccountexpired 2239
-#define ERRbadclient      2240
-#define ERRbadLogonTime   2241
-#define ERRpasswordExpired 2242
-#define ERRnetlogonNotStarted 2455
-#define ERRnosupport       0xFFFF
+/* Following error codes may be generated with the ERRSRV error class.*/
+
+#define ERRerror		1	/* Non-specific error code. It is
+					   returned under the following
+					   conditions: resource other than disk
+					   space exhausted (e.g. TIDs), first
+					   SMB command was not negotiate,
+					   multiple negotiates attempted, and
+					   internal server error. */
+#define ERRbadpw		2	/* Bad password - name/password pair in
+					   a TreeConnect or Session Setup are
+					   invalid. */
+#define ERRbadtype		3	/* used for indicating DFS referral
+					   needed */
+#define ERRaccess		4	/* The client does not have the
+					   necessary access rights within the
+					   specified context for requested
+					   function. */
+#define ERRinvtid		5	/* The Tid specified in a command was
+					   invalid. */
+#define ERRinvnetname		6	/* Invalid network name in tree
+					   connect. */
+#define ERRinvdevice		7	/* Invalid device - printer request
+					   made to non-printer connection or
+					   non-printer request made to printer
+					   connection. */
+#define ERRqfull		49	/* Print queue full (files) -- returned
+					   by open print file. */
+#define ERRqtoobig		50	/* Print queue full -- no space. */
+#define ERRqeof			51	/* EOF on print queue dump */
+#define ERRinvpfid		52	/* Invalid print file FID. */
+#define ERRsmbcmd		64	/* The server did not recognize the
+					   command received. */
+#define ERRsrverror		65	/* The server encountered an internal
+					   error, e.g., system file
+					   unavailable. */
+#define ERRbadBID		66	/* (obsolete) */
+#define ERRfilespecs		67	/* The Fid and pathname parameters
+					   contained an invalid combination of
+					   values. */
+#define ERRbadLink		68	/* (obsolete) */
+#define ERRbadpermits		69	/* The access permissions specified for
+					   a file or directory are not a valid
+					   combination. */
+#define ERRbadPID		70
+#define ERRsetattrmode		71	/* attribute (mode) is invalid */
+#define ERRpaused		81	/* Server is paused */
+#define ERRmsgoff		82	/* reserved - messaging off */
+#define ERRnoroom		83	/* reserved - no room for message */
+#define ERRrmuns		87	/* reserved - too many remote names */
+#define ERRtimeout		88	/* operation timed out */
+#define ERRnoresource		89	/* No resources available for request
+					   */
+#define ERRtoomanyuids		90	/* Too many UIDs active on this session
+					   */
+#define ERRbaduid		91	/* The UID is not known as a valid user
+					   */
+#define ERRusempx		250	/* temporarily unable to use raw */
+#define ERRusestd		251	/* temporarily unable to use either raw
+					   or mpx */
+#define ERR_NOTIFY_ENUM_DIR	1024
+#define ERRaccountexpired	2239
+#define ERRbadclient		2240
+#define ERRbadLogonTime		2241
+#define ERRpasswordExpired	2242
+#define ERRnetlogonNotStarted	2455
+#define ERRnosupport		0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index af13e52..0046c21 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/transport.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
 	struct mid_q_entry *temp;
 
 	if (ses == NULL) {
-		cERROR(1, ("Null session passed in to AllocMidQEntry "));
+		cERROR(1, ("Null session passed in to AllocMidQEntry"));
 		return NULL;
 	}
 	if (ses->server == NULL) {
@@ -79,7 +79,10 @@
 	list_del(&midEntry->qhead);
 	atomic_dec(&midCount);
 	spin_unlock(&GlobalMid_Lock);
-	cifs_buf_release(midEntry->resp_buf);
+	if(midEntry->largeBuf)
+		cifs_buf_release(midEntry->resp_buf);
+	else
+		cifs_small_buf_release(midEntry->resp_buf);
 	mempool_free(midEntry, cifs_mid_poolp);
 }
 
@@ -182,14 +185,14 @@
 
 int
 smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
-	 unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin)
+	 unsigned int smb_buf_length, struct kvec * write_vector 
+	  /* page list */, struct sockaddr *sin)
 {
 	int rc = 0;
 	int i = 0;
 	struct msghdr smb_msg;
 	number_of_pages += 1; /* account for SMB header */
 	struct kvec * piov  = kmalloc(number_of_pages * sizeof(struct kvec));
-	if(i=0;i<num_pages-1;i++
 	unsigned len = smb_buf_length + 4;
 
 	if(ssocket == NULL)
@@ -213,7 +216,8 @@
 	dump_smb(smb_buffer, len);
 
 	while (len > 0) {
-		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?);
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, 
+				    len);
 		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 			i++;
 			if(i > 60) {
@@ -266,6 +270,9 @@
 
   
 
+	if(ses->server->tcpStatus == CIFS_EXITING)
+		return -ENOENT;
+
 	/* Ensure that we do not send more than 50 overlapping requests 
 	   to the same server. We may make this configurable later or
 	   use ses->maxReq */
@@ -346,11 +353,12 @@
 	}
 
 	/* BB can we sign efficiently in this path? */
-	rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 
 	midQ->midState = MID_REQUEST_SUBMITTED;
-/*	rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec,
-		      (struct sockaddr *) &(ses->server->addr.sockAddr));*/
+/*	rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+		       piovec, 
+		       (struct sockaddr *) &(ses->server->addr.sockAddr));*/
 	if(rc < 0) {
 		DeleteMidQEntry(midQ);
 		up(&ses->server->tcpSem);
@@ -396,6 +404,9 @@
 		return -EIO;
 	}
 
+	if(ses->server->tcpStatus == CifsExiting)
+		return -ENOENT;
+
 	/* Ensure that we do not send more than 50 overlapping requests 
 	   to the same server. We may make this configurable later or
 	   use ses->maxReq */
@@ -405,7 +416,8 @@
 	} else {
 		spin_lock(&GlobalMid_Lock); 
 		while(1) {        
-			if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
+			if(atomic_read(&ses->server->inFlight) >= 
+					cifs_max_pending){
 				spin_unlock(&GlobalMid_Lock);
 				wait_event(ses->server->request_q,
 					atomic_read(&ses->server->inFlight)
@@ -475,7 +487,7 @@
 		return -EIO;
 	}
 
-	rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 
 	midQ->midState = MID_REQUEST_SUBMITTED;
 	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
@@ -493,7 +505,7 @@
 		up(&ses->server->tcpSem);
 	if (long_op == -1)
 		goto cifs_no_response_exit;
-	else if (long_op == 2) /* writes past end of file can take looooong time */
+	else if (long_op == 2) /* writes past end of file can take loong time */
 		timeout = 300 * HZ;
 	else if (long_op == 1)
 		timeout = 45 * HZ; /* should be greater than 
@@ -559,8 +571,7 @@
 	}
   
 	if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
-		cERROR(1,
-		       ("Frame too large received.  Length: %d  Xid: %d",
+		cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
 			receive_len, xid));
 		rc = -EIO;
 	} else {		/* rcvd frame is ok */
@@ -575,15 +586,20 @@
 			dump_smb(out_buf, 92);
 			/* convert the length into a more usable form */
 			if((receive_len > 24) &&
-			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
-				rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
-				if(rc)
-					cFYI(1,("Unexpected signature received from server"));
+			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
+					SECMODE_SIGN_ENABLED))) {
+				rc = cifs_verify_signature(out_buf,
+						ses->server->mac_signing_key,
+						midQ->sequence_number+1);
+				if(rc) {
+					cERROR(1,("Unexpected SMB signature"));
+					/* BB FIXME add code to kill session */
+				}
 			}
 
 			*pbytes_returned = out_buf->smb_buf_length;
 
-			/* BB special case reconnect tid and reconnect uid here? */
+			/* BB special case reconnect tid and uid here? */
 			rc = map_smb_to_linux_error(out_buf);
 
 			/* convert ByteCount if necessary */
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 549afa1..c1e02ef 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -83,7 +83,8 @@
 
 		ea_name+=5; /* skip past user. prefix */
 		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
-			(__u16)0, cifs_sb->local_nls);
+			(__u16)0, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	}
 remove_ea_exit:
 	if (full_path)
@@ -147,32 +148,40 @@
 		}
 		ea_name += 5; /* skip past user. prefix */
 		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
-			(__u16)value_size, cifs_sb->local_nls);
+			(__u16)value_size, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
 		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 			goto set_ea_exit;
 
 		ea_name += 4; /* skip past os2. prefix */
 		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
-			(__u16)value_size, cifs_sb->local_nls);
+			(__u16)value_size, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} else {
 		int temp; 
 		temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
 			strlen(POSIX_ACL_XATTR_ACCESS));
 		if (temp == 0) {
 #ifdef CONFIG_CIFS_POSIX
-			rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value,
-				(const int)value_size, ACL_TYPE_ACCESS,
-				cifs_sb->local_nls);
+			if(sb->s_flags & MS_POSIXACL)
+				rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
+					ea_value, (const int)value_size, 
+					ACL_TYPE_ACCESS,cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			cFYI(1,("set POSIX ACL rc %d",rc));
 #else
 			cFYI(1,("set POSIX ACL not supported"));
 #endif
 		} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
-			rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value,
-				(const int)value_size, ACL_TYPE_DEFAULT,
-				cifs_sb->local_nls);
+			if(sb->s_flags & MS_POSIXACL)
+				rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
+					ea_value, (const int)value_size, 
+					ACL_TYPE_DEFAULT, cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags & 
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			cFYI(1,("set POSIX default ACL rc %d",rc));
 #else
 			cFYI(1,("set default POSIX ACL not supported"));
@@ -238,27 +247,35 @@
 		} /* BB add else when above is implemented */
 		ea_name += 5; /* skip past user. prefix */
 		rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
-			buf_size, cifs_sb->local_nls);
+			buf_size, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
 		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 			goto get_ea_exit;
 
 		ea_name += 4; /* skip past os2. prefix */
 		rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
-			buf_size, cifs_sb->local_nls);
+			buf_size, cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
-		rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
+		if(sb->s_flags & MS_POSIXACL)
+			rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
 				ea_value, buf_size, ACL_TYPE_ACCESS, 
-				cifs_sb->local_nls);
+				cifs_sb->local_nls,
+				cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 #else 
 		cFYI(1,("query POSIX ACL not supported yet"));
 #endif /* CONFIG_CIFS_POSIX */
 	} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
 #ifdef CONFIG_CIFS_POSIX
-		rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
+		if(sb->s_flags & MS_POSIXACL)
+			rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
 				ea_value, buf_size, ACL_TYPE_DEFAULT, 
-				cifs_sb->local_nls);
+				cifs_sb->local_nls,
+				cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 #else 
 		cFYI(1,("query POSIX default ACL not supported yet"));
 #endif
@@ -324,7 +341,9 @@
 		search server for EAs or streams to 
 		returns as xattrs */
 	rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
-				cifs_sb->local_nls);
+				cifs_sb->local_nls,
+				cifs_sb->mnt_cifs_flags & 
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 	if (full_path)
 		kfree(full_path);
diff --git a/fs/compat.c b/fs/compat.c
index 67c0b94..728cd83 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -809,7 +809,7 @@
 
 struct compat_nfs_string {
 	compat_uint_t len;
-	compat_uptr_t __user data;
+	compat_uptr_t data;
 };
 
 static inline void compat_nfs_string(struct nfs_string *dst,
@@ -834,10 +834,10 @@
 	struct compat_nfs_string mnt_path;
 	struct compat_nfs_string hostname;
 	compat_uint_t host_addrlen;
-	compat_uptr_t __user host_addr;
+	compat_uptr_t host_addr;
 	compat_int_t proto;
 	compat_int_t auth_flavourlen;
-	compat_uptr_t __user auth_flavours;
+	compat_uptr_t auth_flavours;
 };
 
 static int do_nfs4_super_data_conv(void *raw_data)
diff --git a/fs/dcache.c b/fs/dcache.c
index 496a4e0..3aa8a7e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -39,7 +39,7 @@
 EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
 
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
-seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
+static seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
 
 EXPORT_SYMBOL(dcache_lock);
 
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 05b966c..9900e33 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -320,7 +320,7 @@
 /*
  * This semaphore is used to serialize ep_free() and eventpoll_release_file().
  */
-struct semaphore epsem;
+static struct semaphore epsem;
 
 /* Safe wake up implementation */
 static struct poll_safewake psw;
diff --git a/fs/exec.c b/fs/exec.c
index a839449..e56ee24 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -197,7 +197,8 @@
  * memory to free pages in kernel mem. These are in a format ready
  * to be put directly into the top of new user memory.
  */
-int copy_strings(int argc,char __user * __user * argv, struct linux_binprm *bprm)
+static int copy_strings(int argc, char __user * __user * argv,
+			struct linux_binprm *bprm)
 {
 	struct page *kmapped_page = NULL;
 	char *kaddr = NULL;
@@ -868,9 +869,11 @@
 	if (current->euid == current->uid && current->egid == current->gid)
 		current->mm->dumpable = 1;
 	name = bprm->filename;
+
+	/* Copies the binary name from after last slash */
 	for (i=0; (ch = *(name++)) != '\0';) {
 		if (ch == '/')
-			i = 0;
+			i = 0; /* overwrite what we wrote */
 		else
 			if (i < (sizeof(tcomm) - 1))
 				tcomm[i++] = ch;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 040eb28..0d5fa73 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -455,12 +455,11 @@
  *	@goal:	place to store the result.
  *
  *	Normally this function find the prefered place for block allocation,
- *	stores it in *@goal and returns zero. If the branch had been changed
- *	under us we return -EAGAIN.
+ *	stores it in *@goal and returns zero.
  */
 
-static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4],
-			  Indirect *partial, unsigned long *goal)
+static unsigned long ext3_find_goal(struct inode *inode, long block,
+		Indirect chain[4], Indirect *partial)
 {
 	struct ext3_block_alloc_info *block_i =  EXT3_I(inode)->i_block_alloc_info;
 
@@ -470,15 +469,10 @@
 	 */
 	if (block_i && (block == block_i->last_alloc_logical_block + 1)
 		&& (block_i->last_alloc_physical_block != 0)) {
-		*goal = block_i->last_alloc_physical_block + 1;
-		return 0;
+		return block_i->last_alloc_physical_block + 1;
 	}
 
-	if (verify_chain(chain, partial)) {
-		*goal = ext3_find_near(inode, partial);
-		return 0;
-	}
-	return -EAGAIN;
+	return ext3_find_near(inode, partial);
 }
 
 /**
@@ -582,12 +576,9 @@
  *	@where: location of missing link
  *	@num:   number of blocks we are adding
  *
- *	This function verifies that chain (up to the missing link) had not
- *	changed, fills the missing link and does all housekeeping needed in
+ *	This function fills the missing link and does all housekeeping needed in
  *	inode (->i_blocks, etc.). In case of success we end up with the full
- *	chain to new block and return 0. Otherwise (== chain had been changed)
- *	we free the new blocks (forgetting their buffer_heads, indeed) and
- *	return -EAGAIN.
+ *	chain to new block and return 0.
  */
 
 static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block,
@@ -608,12 +599,6 @@
 		if (err)
 			goto err_out;
 	}
-	/* Verify that place we are splicing to is still there and vacant */
-
-	if (!verify_chain(chain, where-1) || *where->p)
-		/* Writer: end */
-		goto changed;
-
 	/* That's it */
 
 	*where->p = where->key;
@@ -657,26 +642,11 @@
 	}
 	return err;
 
-changed:
-	/*
-	 * AKPM: if where[i].bh isn't part of the current updating
-	 * transaction then we explode nastily.  Test this code path.
-	 */
-	jbd_debug(1, "the chain changed: try again\n");
-	err = -EAGAIN;
-
 err_out:
 	for (i = 1; i < num; i++) {
 		BUFFER_TRACE(where[i].bh, "call journal_forget");
 		ext3_journal_forget(handle, where[i].bh);
 	}
-	/* For the normal collision cleanup case, we free up the blocks.
-	 * On genuine filesystem errors we don't even think about doing
-	 * that. */
-	if (err == -EAGAIN)
-		for (i = 0; i < num; i++)
-			ext3_free_blocks(handle, inode, 
-					 le32_to_cpu(where[i].key), 1);
 	return err;
 }
 
@@ -708,7 +678,7 @@
 	unsigned long goal;
 	int left;
 	int boundary = 0;
-	int depth = ext3_block_to_path(inode, iblock, offsets, &boundary);
+	const int depth = ext3_block_to_path(inode, iblock, offsets, &boundary);
 	struct ext3_inode_info *ei = EXT3_I(inode);
 
 	J_ASSERT(handle != NULL || create == 0);
@@ -716,54 +686,55 @@
 	if (depth == 0)
 		goto out;
 
-reread:
 	partial = ext3_get_branch(inode, depth, offsets, chain, &err);
 
 	/* Simplest case - block found, no allocation needed */
 	if (!partial) {
 		clear_buffer_new(bh_result);
-got_it:
-		map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
-		if (boundary)
-			set_buffer_boundary(bh_result);
-		/* Clean up and exit */
-		partial = chain+depth-1; /* the whole chain */
-		goto cleanup;
+		goto got_it;
 	}
 
 	/* Next simple case - plain lookup or failed read of indirect block */
-	if (!create || err == -EIO) {
-cleanup:
+	if (!create || err == -EIO)
+		goto cleanup;
+
+	down(&ei->truncate_sem);
+
+	/*
+	 * If the indirect block is missing while we are reading
+	 * the chain(ext3_get_branch() returns -EAGAIN err), or
+	 * if the chain has been changed after we grab the semaphore,
+	 * (either because another process truncated this branch, or
+	 * another get_block allocated this branch) re-grab the chain to see if
+	 * the request block has been allocated or not.
+	 *
+	 * Since we already block the truncate/other get_block
+	 * at this point, we will have the current copy of the chain when we
+	 * splice the branch into the tree.
+	 */
+	if (err == -EAGAIN || !verify_chain(chain, partial)) {
 		while (partial > chain) {
-			BUFFER_TRACE(partial->bh, "call brelse");
 			brelse(partial->bh);
 			partial--;
 		}
-		BUFFER_TRACE(bh_result, "returned");
-out:
-		return err;
+		partial = ext3_get_branch(inode, depth, offsets, chain, &err);
+		if (!partial) {
+			up(&ei->truncate_sem);
+			if (err)
+				goto cleanup;
+			clear_buffer_new(bh_result);
+			goto got_it;
+		}
 	}
 
 	/*
-	 * Indirect block might be removed by truncate while we were
-	 * reading it. Handling of that case (forget what we've got and
-	 * reread) is taken out of the main path.
-	 */
-	if (err == -EAGAIN)
-		goto changed;
-
-	goal = 0;
-	down(&ei->truncate_sem);
-
-	/* lazy initialize the block allocation info here if necessary */
-	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) {
+	 * Okay, we need to do block allocation.  Lazily initialize the block
+	 * allocation info here if necessary
+	*/
+	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
 		ext3_init_block_alloc_info(inode);
-	}
 
-	if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) {
-		up(&ei->truncate_sem);
-		goto changed;
-	}
+	goal = ext3_find_goal(inode, iblock, chain, partial);
 
 	left = (chain + depth) - partial;
 
@@ -771,38 +742,45 @@
 	 * Block out ext3_truncate while we alter the tree
 	 */
 	err = ext3_alloc_branch(handle, inode, left, goal,
-					offsets+(partial-chain), partial);
+				offsets + (partial - chain), partial);
 
-	/* The ext3_splice_branch call will free and forget any buffers
+	/*
+	 * The ext3_splice_branch call will free and forget any buffers
 	 * on the new chain if there is a failure, but that risks using
 	 * up transaction credits, especially for bitmaps where the
 	 * credits cannot be returned.  Can we handle this somehow?  We
-	 * may need to return -EAGAIN upwards in the worst case.  --sct */
+	 * may need to return -EAGAIN upwards in the worst case.  --sct
+	 */
 	if (!err)
 		err = ext3_splice_branch(handle, inode, iblock, chain,
 					 partial, left);
-	/* i_disksize growing is protected by truncate_sem
-	 * don't forget to protect it if you're about to implement
-	 * concurrent ext3_get_block() -bzzz */
+	/*
+	 * i_disksize growing is protected by truncate_sem.  Don't forget to
+	 * protect it if you're about to implement concurrent
+	 * ext3_get_block() -bzzz
+	*/
 	if (!err && extend_disksize && inode->i_size > ei->i_disksize)
 		ei->i_disksize = inode->i_size;
 	up(&ei->truncate_sem);
-	if (err == -EAGAIN)
-		goto changed;
 	if (err)
 		goto cleanup;
 
 	set_buffer_new(bh_result);
-	goto got_it;
-
-changed:
+got_it:
+	map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
+	if (boundary)
+		set_buffer_boundary(bh_result);
+	/* Clean up and exit */
+	partial = chain + depth - 1;	/* the whole chain */
+cleanup:
 	while (partial > chain) {
-		jbd_debug(1, "buffer chain changed, retrying\n");
-		BUFFER_TRACE(partial->bh, "brelsing");
+		BUFFER_TRACE(partial->bh, "call brelse");
 		brelse(partial->bh);
 		partial--;
 	}
-	goto reread;
+	BUFFER_TRACE(bh_result, "returned");
+out:
+	return err;
 }
 
 static int ext3_get_block(struct inode *inode, sector_t iblock,
@@ -866,12 +844,6 @@
 	return ret;
 }
 
-static int ext3_writepages_get_block(struct inode *inode, sector_t iblock,
-			struct buffer_head *bh, int create)
-{
-	return ext3_direct_io_get_blocks(inode, iblock, 1, bh, create);
-}
-
 /*
  * `handle' can be NULL if create is zero
  */
@@ -1345,45 +1317,6 @@
 	return ret;
 }
 
-static int
-ext3_writeback_writepage_helper(struct page *page,
-				struct writeback_control *wbc)
-{
-	return block_write_full_page(page, ext3_get_block, wbc);
-}
-
-static int
-ext3_writeback_writepages(struct address_space *mapping,
-				struct writeback_control *wbc)
-{
-	struct inode *inode = mapping->host;
-	handle_t *handle = NULL;
-	int err, ret = 0;
-
-	if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
-		return ret;
-
-	handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
-	if (IS_ERR(handle)) {
-		ret = PTR_ERR(handle);
-		return ret;
-	}
-
-        ret = __mpage_writepages(mapping, wbc, ext3_writepages_get_block,
-					ext3_writeback_writepage_helper);
-
-	/*
-	 * Need to reaquire the handle since ext3_writepages_get_block()
-	 * can restart the handle
-	 */
-	handle = journal_current_handle();
-
-	err = ext3_journal_stop(handle);
-	if (!ret)
-		ret = err;
-	return ret;
-}
-
 static int ext3_writeback_writepage(struct page *page,
 				struct writeback_control *wbc)
 {
@@ -1621,7 +1554,6 @@
 	.readpage	= ext3_readpage,
 	.readpages	= ext3_readpages,
 	.writepage	= ext3_writeback_writepage,
-	.writepages	= ext3_writeback_writepages,
 	.sync_page	= block_sync_page,
 	.prepare_write	= ext3_prepare_write,
 	.commit_write	= ext3_writeback_commit_write,
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 3e7ab16..286a9f8 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include <linux/signal.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
@@ -308,7 +309,7 @@
 		break;
 	case F_SETSIG:
 		/* arg == 0 restores default behaviour. */
-		if (arg < 0 || arg > _NSIG) {
+		if (!valid_signal(arg)) {
 			break;
 		}
 		err = 0;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index d6efb36..8e050fa 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -512,7 +512,8 @@
 }
 
 /**
- * sync_inodes
+ * sync_inodes - writes all inodes to disk
+ * @wait: wait for completion
  *
  * sync_inodes() goes through each super block's dirty inode list, writes the
  * inodes out, waits on the writeout and puts the inodes back on the normal
@@ -604,6 +605,7 @@
 /**
  * generic_osync_inode - flush all dirty data for a given inode to disk
  * @inode: inode to write
+ * @mapping: the address_space that should be flushed
  * @what:  what to write and wait upon
  *
  * This can be called by file_write functions for files which have the
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 4efb640..217e32f 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -333,6 +333,8 @@
  * Release the resources associated with the in-core MDB.  */
 void hfs_mdb_put(struct super_block *sb)
 {
+	if (!HFS_SB(sb))
+		return;
 	/* free the B-trees */
 	hfs_btree_close(HFS_SB(sb)->ext_tree);
 	hfs_btree_close(HFS_SB(sb)->cat_tree);
@@ -340,4 +342,7 @@
 	/* free the buffers holding the primary and alternate MDBs */
 	brelse(HFS_SB(sb)->mdb_bh);
 	brelse(HFS_SB(sb)->alt_mdb_bh);
+
+	kfree(HFS_SB(sb));
+	sb->s_fs_info = NULL;
 }
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1e2c193..ab783f6 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -297,7 +297,7 @@
 	res = -EINVAL;
 	if (!parse_options((char *)data, sbi)) {
 		hfs_warn("hfs_fs: unable to parse mount options.\n");
-		goto bail3;
+		goto bail;
 	}
 
 	sb->s_op = &hfs_super_operations;
@@ -310,7 +310,7 @@
 			hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
 				hfs_mdb_name(sb));
 		res = -EINVAL;
-		goto bail2;
+		goto bail;
 	}
 
 	/* try to get the root inode */
@@ -340,10 +340,8 @@
 	iput(root_inode);
 bail_no_root:
 	hfs_warn("hfs_fs: get root inode failed.\n");
+bail:
 	hfs_mdb_put(sb);
-bail2:
-bail3:
-	kfree(sbi);
 	return res;
 }
 
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 5f80446..d55ad67 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -208,7 +208,9 @@
 static void hfsplus_put_super(struct super_block *sb)
 {
 	dprint(DBG_SUPER, "hfsplus_put_super\n");
-	if (!(sb->s_flags & MS_RDONLY)) {
+	if (!sb->s_fs_info)
+		return;
+	if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) {
 		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
 
 		vhdr->modify_date = hfsp_now2mt();
@@ -226,6 +228,8 @@
 	brelse(HFSPLUS_SB(sb).s_vhbh);
 	if (HFSPLUS_SB(sb).nls)
 		unload_nls(HFSPLUS_SB(sb).nls);
+	kfree(sb->s_fs_info);
+	sb->s_fs_info = NULL;
 }
 
 static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf)
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index a88ad29..14a0d33 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -521,7 +521,7 @@
 static struct address_space_operations hostfs_aops = {
 	.writepage 	= hostfs_writepage,
 	.readpage	= hostfs_readpage,
-/* 	.set_page_dirty = __set_page_dirty_nobuffers, */
+	.set_page_dirty = __set_page_dirty_nobuffers,
 	.prepare_write	= hostfs_prepare_write,
 	.commit_write	= hostfs_commit_write
 };
@@ -991,13 +991,17 @@
 		goto out_put;
 
 	err = read_inode(root_inode);
-	if(err)
-		goto out_put;
+	if(err){
+                /* No iput in this case because the dput does that for us */
+                dput(sb->s_root);
+                sb->s_root = NULL;
+		goto out_free;
+        }
 
 	return(0);
 
  out_put:
-	iput(root_inode);
+        iput(root_inode);
  out_free:
 	kfree(name);
  out:
diff --git a/fs/inode.c b/fs/inode.c
index af8fd78..801fe7f 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -26,7 +26,6 @@
  * This is needed for the following functions:
  *  - inode_has_buffers
  *  - invalidate_inode_buffers
- *  - fsync_bdev
  *  - invalidate_bdev
  *
  * FIXME: remove all knowledge of the buffer layer from this file
@@ -332,14 +331,6 @@
 	return busy;
 }
 
-/*
- * This is a two-stage process. First we collect all
- * offending inodes onto the throw-away list, and in
- * the second stage we actually dispose of them. This
- * is because we don't want to sleep while messing
- * with the global lists..
- */
- 
 /**
  *	invalidate_inodes	- discard the inodes on a device
  *	@sb: superblock
@@ -366,16 +357,11 @@
 
 EXPORT_SYMBOL(invalidate_inodes);
  
-int __invalidate_device(struct block_device *bdev, int do_sync)
+int __invalidate_device(struct block_device *bdev)
 {
-	struct super_block *sb;
-	int res;
+	struct super_block *sb = get_super(bdev);
+	int res = 0;
 
-	if (do_sync)
-		fsync_bdev(bdev);
-
-	res = 0;
-	sb = get_super(bdev);
 	if (sb) {
 		/*
 		 * no need to lock the super, get_super holds the
@@ -390,7 +376,6 @@
 	invalidate_bdev(bdev, 0);
 	return res;
 }
-
 EXPORT_SYMBOL(__invalidate_device);
 
 static int can_unuse(struct inode *inode)
@@ -1336,7 +1321,7 @@
 
 	/* inode slab cache */
 	inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode),
-				0, SLAB_PANIC, init_once, NULL);
+				0, SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_once, NULL);
 	set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
 
 	/* Hash may have been set up in inode_init_early */
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index fb42c3f..34a44e4 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -18,29 +18,12 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-
-#include <linux/stat.h>
-#include <linux/time.h>
-#include <linux/iso_fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/nls.h>
-#include <linux/ctype.h>
-#include <linux/smp_lock.h>
-#include <linux/blkdev.h>
+
 #include <linux/vmalloc.h>
 #include <linux/zlib.h>
-#include <linux/buffer_head.h>
 
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-
+#include "isofs.h"
 #include "zisofs.h"
 
 /* This should probably be global. */
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 14d86de..6030956 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -10,20 +10,9 @@
  * 
  *  isofs directory handling functions
  */
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/iso_fs.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/time.h>
 #include <linux/config.h>
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>
-
-#include <asm/uaccess.h>
+#include "isofs.h"
 
 static int isofs_readdir(struct file *, void *, filldir_t);
 
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index e4252c9..4af856a 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -13,11 +13,7 @@
  *     fs/exportfs/expfs.c.
  */
 
-#include <linux/buffer_head.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/iso_fs.h>
-#include <linux/kernel.h>
+#include "isofs.h"
 
 static struct dentry *
 isofs_export_iget(struct super_block *sb,
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index b9256e6..abd7b12 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -12,29 +12,18 @@
  */
 
 #include <linux/config.h>
+#include <linux/init.h>
 #include <linux/module.h>
 
-#include <linux/stat.h>
-#include <linux/time.h>
-#include <linux/iso_fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/cdrom.h>
-#include <linux/init.h>
 #include <linux/nls.h>
 #include <linux/ctype.h>
 #include <linux/smp_lock.h>
-#include <linux/blkdev.h>
-#include <linux/buffer_head.h>
-#include <linux/vfs.h>
+#include <linux/statfs.h>
+#include <linux/cdrom.h>
 #include <linux/parser.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
 
+#include "isofs.h"
 #include "zisofs.h"
 
 #define BEQUIET
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
new file mode 100644
index 0000000..9ce7b51
--- /dev/null
+++ b/fs/isofs/isofs.h
@@ -0,0 +1,190 @@
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/iso_fs.h>
+#include <asm/unaligned.h>
+
+enum isofs_file_format {
+	isofs_file_normal = 0,
+	isofs_file_sparse = 1,
+	isofs_file_compressed = 2,
+};
+	
+/*
+ * iso fs inode data in memory
+ */
+struct iso_inode_info {
+	unsigned long i_iget5_block;
+	unsigned long i_iget5_offset;
+	unsigned int i_first_extent;
+	unsigned char i_file_format;
+	unsigned char i_format_parm[3];
+	unsigned long i_next_section_block;
+	unsigned long i_next_section_offset;
+	off_t i_section_size;
+	struct inode vfs_inode;
+};
+
+/*
+ * iso9660 super-block data in memory
+ */
+struct isofs_sb_info {
+	unsigned long s_ninodes;
+	unsigned long s_nzones;
+	unsigned long s_firstdatazone;
+	unsigned long s_log_zone_size;
+	unsigned long s_max_size;
+	
+	unsigned char s_high_sierra; /* A simple flag */
+	unsigned char s_mapping;
+	int           s_rock_offset; /* offset of SUSP fields within SU area */
+	unsigned char s_rock;
+	unsigned char s_joliet_level;
+	unsigned char s_utf8;
+	unsigned char s_cruft; /* Broken disks with high
+				  byte of length containing
+				  junk */
+	unsigned char s_unhide;
+	unsigned char s_nosuid;
+	unsigned char s_nodev;
+	unsigned char s_nocompress;
+
+	mode_t s_mode;
+	gid_t s_gid;
+	uid_t s_uid;
+	struct nls_table *s_nls_iocharset; /* Native language support table */
+};
+
+static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+
+static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
+{
+	return container_of(inode, struct iso_inode_info, vfs_inode);
+}
+
+static inline int isonum_711(char *p)
+{
+	return *(u8 *)p;
+}
+static inline int isonum_712(char *p)
+{
+	return *(s8 *)p;
+}
+static inline unsigned int isonum_721(char *p)
+{
+	return le16_to_cpu(get_unaligned((__le16 *)p));
+}
+static inline unsigned int isonum_722(char *p)
+{
+	return be16_to_cpu(get_unaligned((__le16 *)p));
+}
+static inline unsigned int isonum_723(char *p)
+{
+	/* Ignore bigendian datum due to broken mastering programs */
+	return le16_to_cpu(get_unaligned((__le16 *)p));
+}
+static inline unsigned int isonum_731(char *p)
+{
+	return le32_to_cpu(get_unaligned((__le32 *)p));
+}
+static inline unsigned int isonum_732(char *p)
+{
+	return be32_to_cpu(get_unaligned((__le32 *)p));
+}
+static inline unsigned int isonum_733(char *p)
+{
+	/* Ignore bigendian datum due to broken mastering programs */
+	return le32_to_cpu(get_unaligned((__le32 *)p));
+}
+extern int iso_date(char *, int);
+
+struct inode;		/* To make gcc happy */
+
+extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
+extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
+extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *);
+
+int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
+int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
+
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct buffer_head *isofs_bread(struct inode *, sector_t);
+extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
+
+extern struct inode *isofs_iget(struct super_block *sb,
+                                unsigned long block,
+                                unsigned long offset);
+
+/* Because the inode number is no longer relevant to finding the
+ * underlying meta-data for an inode, we are free to choose a more
+ * convenient 32-bit number as the inode number.  The inode numbering
+ * scheme was recommended by Sergey Vlasov and Eric Lammerts. */
+static inline unsigned long isofs_get_ino(unsigned long block,
+					  unsigned long offset,
+					  unsigned long bufbits)
+{
+	return (block << (bufbits - 5)) | (offset >> 5);
+}
+
+/* Every directory can have many redundant directory entries scattered
+ * throughout the directory tree.  First there is the directory entry
+ * with the name of the directory stored in the parent directory.
+ * Then, there is the "." directory entry stored in the directory
+ * itself.  Finally, there are possibly many ".." directory entries
+ * stored in all the subdirectories.
+ *
+ * In order for the NFS get_parent() method to work and for the
+ * general consistency of the dcache, we need to make sure the
+ * "i_iget5_block" and "i_iget5_offset" all point to exactly one of
+ * the many redundant entries for each directory.  We normalize the
+ * block and offset by always making them point to the "."  directory.
+ *
+ * Notice that we do not use the entry for the directory with the name
+ * that is located in the parent directory.  Even though choosing this
+ * first directory is more natural, it is much easier to find the "."
+ * entry in the NFS get_parent() method because it is implicitly
+ * encoded in the "extent + ext_attr_length" fields of _all_ the
+ * redundant entries for the directory.  Thus, it can always be
+ * reached regardless of which directory entry you have in hand.
+ *
+ * This works because the "." entry is simply the first directory
+ * record when you start reading the file that holds all the directory
+ * records, and this file starts at "extent + ext_attr_length" blocks.
+ * Because the "." entry is always the first entry listed in the
+ * directories file, the normalized "offset" value is always 0.
+ *
+ * You should pass the directory entry in "de".  On return, "block"
+ * and "offset" will hold normalized values.  Only directories are
+ * affected making it safe to call even for non-directory file
+ * types. */
+static inline void
+isofs_normalize_block_and_offset(struct iso_directory_record* de,
+				 unsigned long *block,
+				 unsigned long *offset)
+{
+	/* Only directories are normalized. */
+	if (de->flags[0] & 2) {
+		*offset = 0;
+		*block = (unsigned long)isonum_733(de->extent)
+			+ (unsigned long)isonum_711(de->ext_attr_length);
+	}
+}
+
+extern struct inode_operations isofs_dir_inode_operations;
+extern struct file_operations isofs_dir_operations;
+extern struct address_space_operations isofs_symlink_aops;
+extern struct export_operations isofs_export_ops;
+
+/* The following macros are used to check for memory leaks. */
+#ifdef LEAK_CHECK
+#define free_s leak_check_free_s
+#define malloc leak_check_malloc
+#define sb_bread leak_check_bread
+#define brelse leak_check_brelse
+extern void * leak_check_malloc(unsigned int size);
+extern void leak_check_free_s(void * obj, int size);
+extern struct buffer_head * leak_check_bread(struct super_block *sb, int block);
+extern void leak_check_brelse(struct buffer_head * bh);
+#endif /* LEAK_CHECK */
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index 86c50e2..2931de7 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -6,11 +6,9 @@
  *  Joliet: Microsoft's Unicode extensions to iso9660
  */
 
-#include <linux/string.h>
+#include <linux/types.h>
 #include <linux/nls.h>
-#include <linux/mm.h>
-#include <linux/iso_fs.h>
-#include <asm/unaligned.h>
+#include "isofs.h"
 
 /*
  * Convert Unicode 16 to UTF8 or ASCII.
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 9569fc4..690edf3 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -6,20 +6,9 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <linux/time.h>
-#include <linux/iso_fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
 #include <linux/config.h>	/* Joliet? */
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>
-#include <linux/dcache.h>
-
-#include <asm/uaccess.h>
+#include "isofs.h"
 
 /*
  * ok, we cannot use strncmp, as the name is not in our data space.
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 8bdd3e4..089e79c 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -6,17 +6,11 @@
  *  Rock Ridge Extensions to iso9660
  */
 
-#include <linux/stat.h>
-#include <linux/time.h>
-#include <linux/iso_fs.h>
-#include <linux/string.h>
-#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>
-#include <asm/page.h>
 
+#include "isofs.h"
 #include "rock.h"
 
 /* These functions are designed to read the system areas of a directory record
diff --git a/fs/isofs/util.c b/fs/isofs/util.c
index 3f6d9c1..01e1ee7 100644
--- a/fs/isofs/util.c
+++ b/fs/isofs/util.c
@@ -2,9 +2,7 @@
  *  linux/fs/isofs/util.c
  */
 
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <linux/iso_fs.h>
+#include "isofs.h"
 
 /* 
  * We have to convert from a MM/DD/YY format to the Unix ctime format.
@@ -80,4 +78,3 @@
 	}
 	return crtime;
 }		
-	
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index 450d662..0942238 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -228,8 +228,10 @@
 	return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
 }
 #endif
-int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, 
-		   uint32_t *sourcelen, uint32_t *dstlen, void *model)
+static int jffs2_dynrubin_compress(unsigned char *data_in,
+				   unsigned char *cpage_out,
+				   uint32_t *sourcelen, uint32_t *dstlen,
+				   void *model)
 {
 	int bits[8];
 	unsigned char histo[256];
@@ -306,15 +308,19 @@
 }		   
 
 
-int jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, 
-		   uint32_t sourcelen, uint32_t dstlen, void *model)
+static int jffs2_rubinmips_decompress(unsigned char *data_in,
+				      unsigned char *cpage_out,
+				      uint32_t sourcelen, uint32_t dstlen,
+				      void *model)
 {
 	rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
         return 0;
 }
 
-int jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, 
-		   uint32_t sourcelen, uint32_t dstlen, void *model)
+static int jffs2_dynrubin_decompress(unsigned char *data_in,
+				     unsigned char *cpage_out,
+				     uint32_t sourcelen, uint32_t dstlen,
+				     void *model)
 {
 	int bits[8];
 	int c;
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 9f9932c..078a30e 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -69,8 +69,10 @@
 #define free_workspaces() do { } while(0)
 #endif /* __KERNEL__ */
 
-int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, 
-		   uint32_t *sourcelen, uint32_t *dstlen, void *model)
+static int jffs2_zlib_compress(unsigned char *data_in,
+			       unsigned char *cpage_out,
+			       uint32_t *sourcelen, uint32_t *dstlen,
+			       void *model)
 {
 	int ret;
 
@@ -135,8 +137,10 @@
 	return ret;
 }
 
-int jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
-		      uint32_t srclen, uint32_t destlen, void *model)
+static int jffs2_zlib_decompress(unsigned char *data_in,
+				 unsigned char *cpage_out,
+				 uint32_t srclen, uint32_t destlen,
+				 void *model)
 {
 	int ret;
 	int wbits = MAX_WBITS;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 0c607c1..771a554 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -79,8 +79,7 @@
 
 	D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT));
 
-	if (!PageLocked(pg))
-                PAGE_BUG(pg);
+	BUG_ON(!PageLocked(pg));
 
 	pg_buf = kmap(pg);
 	/* FIXME: Can kmap fail? */
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 7bc9066..24a6891 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -175,31 +175,22 @@
 {
 	s64 lblock64 = lblock;
 	int rc = 0;
-	int take_locks;
 	xad_t xad;
 	s64 xaddr;
 	int xflag;
-	s32 xlen;
-
-	/*
-	 * If this is a special inode (imap, dmap)
-	 * the lock should already be taken
-	 */
-	take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I);
+	s32 xlen = max_blocks;
 
 	/*
 	 * Take appropriate lock on inode
 	 */
-	if (take_locks) {
-		if (create)
-			IWRITE_LOCK(ip);
-		else
-			IREAD_LOCK(ip);
-	}
+	if (create)
+		IWRITE_LOCK(ip);
+	else
+		IREAD_LOCK(ip);
 
 	if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
-	    (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)
-	     == 0) && xlen) {
+	    (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
+	    xaddr) {
 		if (xflag & XAD_NOTRECORDED) {
 			if (!create)
 				/*
@@ -238,7 +229,7 @@
 #ifdef _JFS_4K
 	if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad)))
 		goto unlock;
-	rc = extAlloc(ip, max_blocks, lblock64, &xad, FALSE);
+	rc = extAlloc(ip, xlen, lblock64, &xad, FALSE);
 	if (rc)
 		goto unlock;
 
@@ -258,12 +249,10 @@
 	/*
 	 * Release lock on inode
 	 */
-	if (take_locks) {
-		if (create)
-			IWRITE_UNLOCK(ip);
-		else
-			IREAD_UNLOCK(ip);
-	}
+	if (create)
+		IWRITE_UNLOCK(ip);
+	else
+		IREAD_UNLOCK(ip);
 	return rc;
 }
 
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index d86e467..69007fd 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -471,6 +471,7 @@
 	struct metapage *mp;
 	struct jfs_log *log;
 	int lsn, difft, diffp;
+	unsigned long flags;
 
 	/* the blocks better be within the mapsize. */
 	if (blkno + nblocks > bmp->db_mapsize) {
@@ -504,6 +505,7 @@
 					   0);
 			if (mp == NULL)
 				return -EIO;
+			metapage_wait_for_io(mp);
 		}
 		dp = (struct dmap *) mp->data;
 
@@ -578,34 +580,32 @@
 		if (mp->lsn != 0) {
 			/* inherit older/smaller lsn */
 			logdiff(diffp, mp->lsn, log);
+			LOGSYNC_LOCK(log, flags);
 			if (difft < diffp) {
 				mp->lsn = lsn;
 
 				/* move bp after tblock in logsync list */
-				LOGSYNC_LOCK(log);
 				list_move(&mp->synclist, &tblk->synclist);
-				LOGSYNC_UNLOCK(log);
 			}
 
 			/* inherit younger/larger clsn */
-			LOGSYNC_LOCK(log);
 			logdiff(difft, tblk->clsn, log);
 			logdiff(diffp, mp->clsn, log);
 			if (difft > diffp)
 				mp->clsn = tblk->clsn;
-			LOGSYNC_UNLOCK(log);
+			LOGSYNC_UNLOCK(log, flags);
 		} else {
 			mp->log = log;
 			mp->lsn = lsn;
 
 			/* insert bp after tblock in logsync list */
-			LOGSYNC_LOCK(log);
+			LOGSYNC_LOCK(log, flags);
 
 			log->count++;
 			list_add(&mp->synclist, &tblk->synclist);
 
 			mp->clsn = tblk->clsn;
-			LOGSYNC_UNLOCK(log);
+			LOGSYNC_UNLOCK(log, flags);
 		}
 	}
 
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index e357890..ac41f72 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -212,7 +212,7 @@
 	s32 xlen;
 
 	rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
-	if (rc || (xlen == 0))
+	if (rc || (xaddr == 0))
 		return NULL;
 
 	return read_metapage(inode, xaddr, PSIZE, 1);
@@ -231,7 +231,7 @@
 	s32 xlen;
 
 	rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
-	if (rc || (xlen == 0))
+	if (rc || (xaddr == 0))
 		return NULL;
 
 	return get_metapage(inode, xaddr, PSIZE, 1);
@@ -3181,7 +3181,7 @@
 			d = (struct ldtentry *) & p->slot[stbl[i]];
 
 			if (((long) jfs_dirent + d->namlen + 1) >
-			    (dirent_buf + PSIZE)) {
+			    (dirent_buf + PAGE_SIZE)) {
 				/* DBCS codepages could overrun dirent_buf */
 				index = i;
 				overflow = 1;
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 7838313..7acff2c 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -502,7 +502,7 @@
 
 	}
 
-	ip->i_mapping->a_ops = &jfs_aops;
+	ip->i_mapping->a_ops = &jfs_metapage_aops;
 	mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
 
 	/* Allocations to metadata inodes should not affect quotas */
@@ -2573,9 +2573,18 @@
 			goto out;
 		}
 
-		/* assign a buffer for the page */
-		mp = get_metapage(ipimap, xaddr, PSIZE, 1);
-		if (!mp) {
+		/*
+		 * start transaction of update of the inode map
+		 * addressing structure pointing to the new iag page;
+		 */
+		tid = txBegin(sb, COMMIT_FORCE);
+		down(&JFS_IP(ipimap)->commit_sem);
+
+		/* update the inode map addressing structure to point to it */
+		if ((rc =
+		     xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
+			txEnd(tid);
+			up(&JFS_IP(ipimap)->commit_sem);
 			/* Free the blocks allocated for the iag since it was
 			 * not successfully added to the inode map
 			 */
@@ -2584,6 +2593,29 @@
 			/* release the inode map lock */
 			IWRITE_UNLOCK(ipimap);
 
+			goto out;
+		}
+
+		/* update the inode map's inode to reflect the extension */
+		ipimap->i_size += PSIZE;
+		inode_add_bytes(ipimap, PSIZE);
+
+		/* assign a buffer for the page */
+		mp = get_metapage(ipimap, blkno, PSIZE, 0);
+		if (!mp) {
+			/*
+			 * This is very unlikely since we just created the
+			 * extent, but let's try to handle it correctly
+			 */
+			xtTruncate(tid, ipimap, ipimap->i_size - PSIZE,
+				   COMMIT_PWMAP);
+
+			txAbort(tid, 0);
+			txEnd(tid);
+
+			/* release the inode map lock */
+			IWRITE_UNLOCK(ipimap);
+
 			rc = -EIO;
 			goto out;
 		}
@@ -2605,41 +2637,11 @@
 			iagp->inosmap[i] = cpu_to_le32(ONES);
 
 		/*
-		 * Invalidate the page after writing and syncing it.
-		 * After it's initialized, we access it in a different
-		 * address space
+		 * Write and sync the metapage
 		 */
-		set_bit(META_discard, &mp->flag);
 		flush_metapage(mp);
 
 		/*
-		 * start tyransaction of update of the inode map
-		 * addressing structure pointing to the new iag page;
-		 */
-		tid = txBegin(sb, COMMIT_FORCE);
-		down(&JFS_IP(ipimap)->commit_sem);
-
-		/* update the inode map addressing structure to point to it */
-		if ((rc =
-		     xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) {
-			txEnd(tid);
-			up(&JFS_IP(ipimap)->commit_sem);
-			/* Free the blocks allocated for the iag since it was
-			 * not successfully added to the inode map
-			 */
-			dbFree(ipimap, xaddr, (s64) xlen);
-
-			/* release the inode map lock */
-			IWRITE_UNLOCK(ipimap);
-
-			goto out;
-		}
-
-		/* update the inode map's inode to reflect the extension */
-		ipimap->i_size += PSIZE;
-		inode_add_bytes(ipimap, PSIZE);
-
-		/*
 		 * txCommit(COMMIT_FORCE) will synchronously write address 
 		 * index pages and inode after commit in careful update order 
 		 * of address index pages (right to left, bottom up);
@@ -2789,6 +2791,7 @@
 	u32 mask;
 	struct jfs_log *log;
 	int lsn, difft, diffp;
+	unsigned long flags;
 
 	imap = JFS_IP(ipimap)->i_imap;
 	/* get the iag number containing the inode */
@@ -2805,6 +2808,7 @@
 	IREAD_UNLOCK(ipimap);
 	if (rc)
 		return (rc);
+	metapage_wait_for_io(mp);
 	iagp = (struct iag *) mp->data;
 	/* get the inode number and extent number of the inode within
 	 * the iag and the inode number within the extent.
@@ -2868,30 +2872,28 @@
 		/* inherit older/smaller lsn */
 		logdiff(difft, lsn, log);
 		logdiff(diffp, mp->lsn, log);
+		LOGSYNC_LOCK(log, flags);
 		if (difft < diffp) {
 			mp->lsn = lsn;
 			/* move mp after tblock in logsync list */
-			LOGSYNC_LOCK(log);
 			list_move(&mp->synclist, &tblk->synclist);
-			LOGSYNC_UNLOCK(log);
 		}
 		/* inherit younger/larger clsn */
-		LOGSYNC_LOCK(log);
 		assert(mp->clsn);
 		logdiff(difft, tblk->clsn, log);
 		logdiff(diffp, mp->clsn, log);
 		if (difft > diffp)
 			mp->clsn = tblk->clsn;
-		LOGSYNC_UNLOCK(log);
+		LOGSYNC_UNLOCK(log, flags);
 	} else {
 		mp->log = log;
 		mp->lsn = lsn;
 		/* insert mp after tblock in logsync list */
-		LOGSYNC_LOCK(log);
+		LOGSYNC_LOCK(log, flags);
 		log->count++;
 		list_add(&mp->synclist, &tblk->synclist);
 		mp->clsn = tblk->clsn;
-		LOGSYNC_UNLOCK(log);
+		LOGSYNC_UNLOCK(log, flags);
 	}
 	write_metapage(mp);
 	return (0);
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index ebd77c1..c0fd7b3 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -165,6 +165,7 @@
         /* Formerly in ipbmap */
 	struct bmap	*bmap;		/* incore bmap descriptor	*/
 	struct nls_table *nls_tab;	/* current codepage		*/
+	struct inode *direct_inode;	/* metadata inode */
 	uint		state;		/* mount/recovery state	*/
 	unsigned long	flag;		/* mount time flags */
 	uint		p_state;	/* state prior to going no integrity */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index b6a6869..dfa1200 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -234,6 +234,7 @@
 	int lsn;
 	int diffp, difft;
 	struct metapage *mp = NULL;
+	unsigned long flags;
 
 	jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p",
 		 log, tblk, lrd, tlck);
@@ -254,7 +255,7 @@
 	 */
 	lsn = log->lsn;
 
-	LOGSYNC_LOCK(log);
+	LOGSYNC_LOCK(log, flags);
 
 	/*
 	 * initialize page lsn if first log write of the page
@@ -310,7 +311,7 @@
 		}
 	}
 
-	LOGSYNC_UNLOCK(log);
+	LOGSYNC_UNLOCK(log, flags);
 
 	/*
 	 *      write the log record
@@ -334,7 +335,6 @@
 	return lsn;
 }
 
-
 /*
  * NAME:	lmWriteRecord()
  *
@@ -927,9 +927,8 @@
  *	calculate new value of i_nextsync which determines when
  *	this code is called again.
  *
- *	this is called only from lmLog().
- *
- * PARAMETER:	ip	- pointer to logs inode.
+ * PARAMETERS:	log	- log structure
+ * 		nosyncwait - 1 if called asynchronously
  *
  * RETURN:	0
  *			
@@ -945,6 +944,15 @@
 	struct lrd lrd;
 	int lsn;
 	struct logsyncblk *lp;
+	struct jfs_sb_info *sbi;
+	unsigned long flags;
+
+	/* push dirty metapages out to disk */
+	list_for_each_entry(sbi, &log->sb_list, log_list) {
+		filemap_flush(sbi->ipbmap->i_mapping);
+		filemap_flush(sbi->ipimap->i_mapping);
+		filemap_flush(sbi->direct_inode->i_mapping);
+	}
 
 	/*
 	 *      forward syncpt
@@ -954,10 +962,7 @@
 	 */
 
 	if (log->sync == log->syncpt) {
-		LOGSYNC_LOCK(log);
-		/* ToDo: push dirty metapages out to disk */
-//              bmLogSync(log);
-
+		LOGSYNC_LOCK(log, flags);
 		if (list_empty(&log->synclist))
 			log->sync = log->lsn;
 		else {
@@ -965,7 +970,7 @@
 					struct logsyncblk, synclist);
 			log->sync = lp->lsn;
 		}
-		LOGSYNC_UNLOCK(log);
+		LOGSYNC_UNLOCK(log, flags);
 
 	}
 
@@ -974,27 +979,6 @@
 	 * reset syncpt = sync
 	 */
 	if (log->sync != log->syncpt) {
-		struct jfs_sb_info *sbi;
-
-		/*
-		 * We need to make sure all of the "written" metapages
-		 * actually make it to disk
-		 */
-		list_for_each_entry(sbi, &log->sb_list, log_list) {
-			if (sbi->flag & JFS_NOINTEGRITY)
-				continue;
-			filemap_fdatawrite(sbi->ipbmap->i_mapping);
-			filemap_fdatawrite(sbi->ipimap->i_mapping);
-			filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping);
-		}
-		list_for_each_entry(sbi, &log->sb_list, log_list) {
-			if (sbi->flag & JFS_NOINTEGRITY)
-				continue;
-			filemap_fdatawait(sbi->ipbmap->i_mapping);
-			filemap_fdatawait(sbi->ipimap->i_mapping);
-			filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping);
-		}
-
 		lrd.logtid = 0;
 		lrd.backchain = 0;
 		lrd.type = cpu_to_le16(LOG_SYNCPT);
@@ -1066,6 +1050,18 @@
 	return lsn;
 }
 
+/*
+ * NAME:	jfs_syncpt
+ *
+ * FUNCTION:	write log SYNCPT record for specified log
+ *
+ * PARAMETERS:	log	- log structure
+ */
+void jfs_syncpt(struct jfs_log *log)
+{	LOG_LOCK(log);
+	lmLogSync(log, 1);
+	LOG_UNLOCK(log);
+}
 
 /*
  * NAME:	lmLogOpen()
@@ -1547,6 +1543,7 @@
 {
 	int i;
 	struct tblock *target = NULL;
+	struct jfs_sb_info *sbi;
 
 	/* jfs_write_inode may call us during read-only mount */
 	if (!log)
@@ -1608,12 +1605,18 @@
 	if (wait < 2)
 		return;
 
+	list_for_each_entry(sbi, &log->sb_list, log_list) {
+		filemap_fdatawrite(sbi->ipbmap->i_mapping);
+		filemap_fdatawrite(sbi->ipimap->i_mapping);
+		filemap_fdatawrite(sbi->direct_inode->i_mapping);
+	}
+
 	/*
 	 * If there was recent activity, we may need to wait
 	 * for the lazycommit thread to catch up
 	 */
 	if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
-		for (i = 0; i < 800; i++) {	/* Too much? */
+		for (i = 0; i < 200; i++) {	/* Too much? */
 			msleep(250);
 			if (list_empty(&log->cqueue) &&
 			    list_empty(&log->synclist))
@@ -1621,7 +1624,24 @@
 		}
 	}
 	assert(list_empty(&log->cqueue));
-	assert(list_empty(&log->synclist));
+	if (!list_empty(&log->synclist)) {
+		struct logsyncblk *lp;
+
+		list_for_each_entry(lp, &log->synclist, synclist) {
+			if (lp->xflag & COMMIT_PAGE) {
+				struct metapage *mp = (struct metapage *)lp;
+				dump_mem("orphan metapage", lp,
+					 sizeof(struct metapage));
+				dump_mem("page", mp->page, sizeof(struct page));
+			}
+			else
+				dump_mem("orphan tblock", lp,
+					 sizeof(struct tblock));
+		}
+//		current->state = TASK_INTERRUPTIBLE;
+//		schedule();
+	}
+	//assert(list_empty(&log->synclist));
 	clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1669,6 +1689,7 @@
 	lp->h.eor = lp->t.eor = cpu_to_le16(bp->l_eor);
 	lbmWrite(log, log->bp, lbmWRITE | lbmRELEASE | lbmSYNC, 0);
 	lbmIOWait(log->bp, lbmFREE);
+	log->bp = NULL;
 
 	/*
 	 * synchronous update log superblock
@@ -1819,20 +1840,34 @@
 
 	log->lbuf_free = NULL;
 
-	for (i = 0; i < LOGPAGES; i++) {
-		lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL);
-		if (lbuf == 0)
-			goto error;
-		lbuf->l_ldata = (char *) get_zeroed_page(GFP_KERNEL);
-		if (lbuf->l_ldata == 0) {
-			kfree(lbuf);
-			goto error;
-		}
-		lbuf->l_log = log;
-		init_waitqueue_head(&lbuf->l_ioevent);
+	for (i = 0; i < LOGPAGES;) {
+		char *buffer;
+		uint offset;
+		struct page *page;
 
-		lbuf->l_freelist = log->lbuf_free;
-		log->lbuf_free = lbuf;
+		buffer = (char *) get_zeroed_page(GFP_KERNEL);
+		if (buffer == NULL)
+			goto error;
+		page = virt_to_page(buffer);
+		for (offset = 0; offset < PAGE_SIZE; offset += LOGPSIZE) {
+			lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL);
+			if (lbuf == NULL) {
+				if (offset == 0)
+					free_page((unsigned long) buffer);
+				goto error;
+			}
+			if (offset) /* we already have one reference */
+				get_page(page);
+			lbuf->l_offset = offset;
+			lbuf->l_ldata = buffer + offset;
+			lbuf->l_page = page;
+			lbuf->l_log = log;
+			init_waitqueue_head(&lbuf->l_ioevent);
+
+			lbuf->l_freelist = log->lbuf_free;
+			log->lbuf_free = lbuf;
+			i++;
+		}
 	}
 
 	return (0);
@@ -1857,12 +1892,10 @@
 	lbuf = log->lbuf_free;
 	while (lbuf) {
 		struct lbuf *next = lbuf->l_freelist;
-		free_page((unsigned long) lbuf->l_ldata);
+		__free_page(lbuf->l_page);
 		kfree(lbuf);
 		lbuf = next;
 	}
-
-	log->bp = NULL;
 }
 
 
@@ -1974,9 +2007,9 @@
 
 	bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
 	bio->bi_bdev = log->bdev;
-	bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata);
+	bio->bi_io_vec[0].bv_page = bp->l_page;
 	bio->bi_io_vec[0].bv_len = LOGPSIZE;
-	bio->bi_io_vec[0].bv_offset = 0;
+	bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
 	bio->bi_vcnt = 1;
 	bio->bi_idx = 0;
@@ -2115,9 +2148,9 @@
 	bio = bio_alloc(GFP_NOFS, 1);
 	bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
 	bio->bi_bdev = log->bdev;
-	bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata);
+	bio->bi_io_vec[0].bv_page = bp->l_page;
 	bio->bi_io_vec[0].bv_len = LOGPSIZE;
-	bio->bi_io_vec[0].bv_offset = 0;
+	bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
 	bio->bi_vcnt = 1;
 	bio->bi_idx = 0;
@@ -2127,16 +2160,13 @@
 	bio->bi_private = bp;
 
 	/* check if journaling to disk has been disabled */
-	if (!log->no_integrity) {
+	if (log->no_integrity) {
+		bio->bi_size = 0;
+		lbmIODone(bio, 0, 0);
+	} else {
 		submit_bio(WRITE_SYNC, bio);
 		INCREMENT(lmStat.submitted);
 	}
-	else {
-		bio->bi_size = 0;
-		lbmIODone(bio, 0, 0); /* 2nd argument appears to not be used => 0
-				       *  3rd argument appears to not be used => 0
-				       */
-	}
 }
 
 
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 141ad74..51291fb 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -463,9 +463,10 @@
 
 	s64 l_blkno;		/* 8: log page block number */
 	caddr_t l_ldata;	/* 4: data page */
+	struct page *l_page;	/* The page itself */
+	uint l_offset;		/* Offset of l_ldata within the page */	
 
 	wait_queue_head_t l_ioevent;	/* 4: i/o done event */
-	struct page *l_page;	/* The page itself */
 };
 
 /* Reuse l_freelist for redrive list */
@@ -489,8 +490,9 @@
  */
 
 #define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock)
-#define LOGSYNC_LOCK(log) spin_lock(&(log)->synclock)
-#define LOGSYNC_UNLOCK(log) spin_unlock(&(log)->synclock)
+#define LOGSYNC_LOCK(log, flags) spin_lock_irqsave(&(log)->synclock, flags)
+#define LOGSYNC_UNLOCK(log, flags) \
+	spin_unlock_irqrestore(&(log)->synclock, flags)
 
 /* compute the difference in bytes of lsn from sync point */
 #define logdiff(diff, lsn, log)\
@@ -506,5 +508,6 @@
 extern int lmLogInit(struct jfs_log * log);
 extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
 extern void jfs_flush_journal(struct jfs_log * log, int wait);
+extern void jfs_syncpt(struct jfs_log *log);
 
 #endif				/* _H_JFS_LOGMGR */
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 4c0a3ac..41bf078 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2005
  *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
@@ -18,10 +18,11 @@
  */
 
 #include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/bio.h>
 #include <linux/init.h>
 #include <linux/buffer_head.h>
 #include <linux/mempool.h>
-#include <linux/delay.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_filsys.h"
@@ -29,8 +30,6 @@
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
-static DEFINE_SPINLOCK(meta_lock);
-
 #ifdef CONFIG_JFS_STATISTICS
 static struct {
 	uint	pagealloc;	/* # of page allocations */
@@ -39,22 +38,8 @@
 } mpStat;
 #endif
 
-
-#define HASH_BITS 10		/* This makes hash_table 1 4K page */
-#define HASH_SIZE (1 << HASH_BITS)
-static struct metapage **hash_table = NULL;
-static unsigned long hash_order;
-
-
-static inline int metapage_locked(struct metapage *mp)
-{
-	return test_bit(META_locked, &mp->flag);
-}
-
-static inline int trylock_metapage(struct metapage *mp)
-{
-	return test_and_set_bit(META_locked, &mp->flag);
-}
+#define metapage_locked(mp) test_bit(META_locked, &(mp)->flag)
+#define trylock_metapage(mp) test_and_set_bit(META_locked, &(mp)->flag)
 
 static inline void unlock_metapage(struct metapage *mp)
 {
@@ -62,26 +47,26 @@
 	wake_up(&mp->wait);
 }
 
-static void __lock_metapage(struct metapage *mp)
+static inline void __lock_metapage(struct metapage *mp)
 {
 	DECLARE_WAITQUEUE(wait, current);
-
 	INCREMENT(mpStat.lockwait);
-
 	add_wait_queue_exclusive(&mp->wait, &wait);
 	do {
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		if (metapage_locked(mp)) {
-			spin_unlock(&meta_lock);
+			unlock_page(mp->page);
 			schedule();
-			spin_lock(&meta_lock);
+			lock_page(mp->page);
 		}
 	} while (trylock_metapage(mp));
 	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&mp->wait, &wait);
 }
 
-/* needs meta_lock */
+/*
+ * Must have mp->page locked
+ */
 static inline void lock_metapage(struct metapage *mp)
 {
 	if (trylock_metapage(mp))
@@ -92,6 +77,110 @@
 static kmem_cache_t *metapage_cache;
 static mempool_t *metapage_mempool;
 
+#define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE)
+
+#if MPS_PER_PAGE > 1
+
+struct meta_anchor {
+	int mp_count;
+	atomic_t io_count;
+	struct metapage *mp[MPS_PER_PAGE];
+};
+#define mp_anchor(page) ((struct meta_anchor *)page->private)
+
+static inline struct metapage *page_to_mp(struct page *page, uint offset)
+{
+	if (!PagePrivate(page))
+		return NULL;
+	return mp_anchor(page)->mp[offset >> L2PSIZE];
+}
+
+static inline int insert_metapage(struct page *page, struct metapage *mp)
+{
+	struct meta_anchor *a;
+	int index;
+	int l2mp_blocks;	/* log2 blocks per metapage */
+
+	if (PagePrivate(page))
+		a = mp_anchor(page);
+	else {
+		a = kmalloc(sizeof(struct meta_anchor), GFP_NOFS);
+		if (!a)
+			return -ENOMEM;
+		memset(a, 0, sizeof(struct meta_anchor));
+		page->private = (unsigned long)a;
+		SetPagePrivate(page);
+		kmap(page);
+	}
+
+	if (mp) {
+		l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits;
+		index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1);
+		a->mp_count++;
+		a->mp[index] = mp;
+	}
+
+	return 0;
+}
+
+static inline void remove_metapage(struct page *page, struct metapage *mp)
+{
+	struct meta_anchor *a = mp_anchor(page);
+	int l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits;
+	int index;
+
+	index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1);
+
+	BUG_ON(a->mp[index] != mp);
+
+	a->mp[index] = NULL;
+	if (--a->mp_count == 0) {
+		kfree(a);
+		page->private = 0;
+		ClearPagePrivate(page);
+		kunmap(page);
+	}
+}
+
+static inline void inc_io(struct page *page)
+{
+	atomic_inc(&mp_anchor(page)->io_count);
+}
+
+static inline void dec_io(struct page *page, void (*handler) (struct page *))
+{
+	if (atomic_dec_and_test(&mp_anchor(page)->io_count))
+		handler(page);
+}
+
+#else
+static inline struct metapage *page_to_mp(struct page *page, uint offset)
+{
+	return PagePrivate(page) ? (struct metapage *)page->private : NULL;
+}
+
+static inline int insert_metapage(struct page *page, struct metapage *mp)
+{
+	if (mp) {
+		page->private = (unsigned long)mp;
+		SetPagePrivate(page);
+		kmap(page);
+	}
+	return 0;
+}
+
+static inline void remove_metapage(struct page *page, struct metapage *mp)
+{
+	page->private = 0;
+	ClearPagePrivate(page);
+	kunmap(page);
+}
+
+#define inc_io(page) do {} while(0)
+#define dec_io(page, handler) handler(page)
+
+#endif
+
 static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
 {
 	struct metapage *mp = (struct metapage *)foo;
@@ -139,16 +228,6 @@
 		kmem_cache_destroy(metapage_cache);
 		return -ENOMEM;
 	}
-	/*
-	 * Now the hash list
-	 */
-	for (hash_order = 0;
-	     ((PAGE_SIZE << hash_order) / sizeof(void *)) < HASH_SIZE;
-	     hash_order++);
-	hash_table =
-	    (struct metapage **) __get_free_pages(GFP_KERNEL, hash_order);
-	assert(hash_table);
-	memset(hash_table, 0, PAGE_SIZE << hash_order);
 
 	return 0;
 }
@@ -159,73 +238,388 @@
 	kmem_cache_destroy(metapage_cache);
 }
 
+static inline void drop_metapage(struct page *page, struct metapage *mp)
+{
+	if (mp->count || mp->nohomeok || test_bit(META_dirty, &mp->flag) ||
+	    test_bit(META_io, &mp->flag))
+		return;
+	remove_metapage(page, mp);
+	INCREMENT(mpStat.pagefree);
+	free_metapage(mp);
+}
+
 /*
- * Basically same hash as in pagemap.h, but using our hash table
+ * Metapage address space operations
  */
-static struct metapage **meta_hash(struct address_space *mapping,
-				   unsigned long index)
+
+static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock,
+				    unsigned int *len)
 {
-#define i (((unsigned long)mapping)/ \
-	   (sizeof(struct inode) & ~(sizeof(struct inode) -1 )))
-#define s(x) ((x) + ((x) >> HASH_BITS))
-	return hash_table + (s(i + index) & (HASH_SIZE - 1));
-#undef i
-#undef s
+	int rc = 0;
+	int xflag;
+	s64 xaddr;
+	sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >>
+			       inode->i_blkbits;
+
+	if (lblock >= file_blocks)
+		return 0;
+	if (lblock + *len > file_blocks)
+		*len = file_blocks - lblock;
+
+	if (inode->i_ino) {
+		rc = xtLookup(inode, (s64)lblock, *len, &xflag, &xaddr, len, 0);
+		if ((rc == 0) && *len)
+			lblock = (sector_t)xaddr;
+		else
+			lblock = 0;
+	} /* else no mapping */
+
+	return lblock;
 }
 
-static struct metapage *search_hash(struct metapage ** hash_ptr,
-				    struct address_space *mapping,
-			       unsigned long index)
+static void last_read_complete(struct page *page)
 {
-	struct metapage *ptr;
+	if (!PageError(page))
+		SetPageUptodate(page);
+	unlock_page(page);
+}
 
-	for (ptr = *hash_ptr; ptr; ptr = ptr->hash_next) {
-		if ((ptr->mapping == mapping) && (ptr->index == index))
-			return ptr;
+static int metapage_read_end_io(struct bio *bio, unsigned int bytes_done,
+				int err)
+{
+	struct page *page = bio->bi_private;
+
+	if (bio->bi_size)
+		return 1;
+
+	if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+		printk(KERN_ERR "metapage_read_end_io: I/O error\n");
+		SetPageError(page);
 	}
 
-	return NULL;
+	dec_io(page, last_read_complete);
+	bio_put(bio);
+
+	return 0;
 }
 
-static void add_to_hash(struct metapage * mp, struct metapage ** hash_ptr)
+static void remove_from_logsync(struct metapage *mp)
 {
-	if (*hash_ptr)
-		(*hash_ptr)->hash_prev = mp;
+	struct jfs_log *log = mp->log;
+	unsigned long flags;
+/*
+ * This can race.  Recheck that log hasn't been set to null, and after
+ * acquiring logsync lock, recheck lsn
+ */
+	if (!log)
+		return;
 
-	mp->hash_prev = NULL;
-	mp->hash_next = *hash_ptr;
-	*hash_ptr = mp;
-}
-
-static void remove_from_hash(struct metapage * mp, struct metapage ** hash_ptr)
-{
-	if (mp->hash_prev)
-		mp->hash_prev->hash_next = mp->hash_next;
-	else {
-		assert(*hash_ptr == mp);
-		*hash_ptr = mp->hash_next;
+	LOGSYNC_LOCK(log, flags);
+	if (mp->lsn) {
+		mp->log = NULL;
+		mp->lsn = 0;
+		mp->clsn = 0;
+		log->count--;
+		list_del(&mp->synclist);
 	}
-
-	if (mp->hash_next)
-		mp->hash_next->hash_prev = mp->hash_prev;
+	LOGSYNC_UNLOCK(log, flags);
 }
 
+static void last_write_complete(struct page *page)
+{
+	struct metapage *mp;
+	unsigned int offset;
+
+	for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+		mp = page_to_mp(page, offset);
+		if (mp && test_bit(META_io, &mp->flag)) {
+			if (mp->lsn)
+				remove_from_logsync(mp);
+			clear_bit(META_io, &mp->flag);
+		}
+		/*
+		 * I'd like to call drop_metapage here, but I don't think it's
+		 * safe unless I have the page locked
+		 */
+	}
+	end_page_writeback(page);
+}
+
+static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done,
+				 int err)
+{
+	struct page *page = bio->bi_private;
+
+	BUG_ON(!PagePrivate(page));
+
+	if (bio->bi_size)
+		return 1;
+
+	if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+		printk(KERN_ERR "metapage_write_end_io: I/O error\n");
+		SetPageError(page);
+	}
+	dec_io(page, last_write_complete);
+	bio_put(bio);
+	return 0;
+}
+
+static int metapage_writepage(struct page *page, struct writeback_control *wbc)
+{
+	struct bio *bio = NULL;
+	unsigned int block_offset;	/* block offset of mp within page */
+	struct inode *inode = page->mapping->host;
+	unsigned int blocks_per_mp = JFS_SBI(inode->i_sb)->nbperpage;
+	unsigned int len;
+	unsigned int xlen;
+	struct metapage *mp;
+	int redirty = 0;
+	sector_t lblock;
+	sector_t pblock;
+	sector_t next_block = 0;
+	sector_t page_start;
+	unsigned long bio_bytes = 0;
+	unsigned long bio_offset = 0;
+	unsigned int offset;
+
+	page_start = (sector_t)page->index <<
+		     (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	BUG_ON(!PageLocked(page));
+	BUG_ON(PageWriteback(page));
+
+	for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+		mp = page_to_mp(page, offset);
+
+		if (!mp || !test_bit(META_dirty, &mp->flag))
+			continue;
+
+		if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) {
+			redirty = 1;
+			continue;
+		}
+
+		clear_bit(META_dirty, &mp->flag);
+		block_offset = offset >> inode->i_blkbits;
+		lblock = page_start + block_offset;
+		if (bio) {
+			if (xlen && lblock == next_block) {
+				/* Contiguous, in memory & on disk */
+				len = min(xlen, blocks_per_mp);
+				xlen -= len;
+				bio_bytes += len << inode->i_blkbits;
+				set_bit(META_io, &mp->flag);
+				continue;
+			}
+			/* Not contiguous */
+			if (bio_add_page(bio, page, bio_bytes, bio_offset) <
+			    bio_bytes)
+				goto add_failed;
+			/*
+			 * Increment counter before submitting i/o to keep
+			 * count from hitting zero before we're through
+			 */
+			inc_io(page);
+			if (!bio->bi_size)
+				goto dump_bio;
+			submit_bio(WRITE, bio);
+			bio = NULL;
+		} else {
+			set_page_writeback(page);
+			inc_io(page);
+		}
+		xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;
+		pblock = metapage_get_blocks(inode, lblock, &xlen);
+		if (!pblock) {
+			/* Need better error handling */
+			printk(KERN_ERR "JFS: metapage_get_blocks failed\n");
+			dec_io(page, last_write_complete);
+			continue;
+		}
+		set_bit(META_io, &mp->flag);
+		len = min(xlen, (uint) JFS_SBI(inode->i_sb)->nbperpage);
+
+		bio = bio_alloc(GFP_NOFS, 1);
+		bio->bi_bdev = inode->i_sb->s_bdev;
+		bio->bi_sector = pblock << (inode->i_blkbits - 9);
+		bio->bi_end_io = metapage_write_end_io;
+		bio->bi_private = page;
+
+		/* Don't call bio_add_page yet, we may add to this vec */
+		bio_offset = offset;
+		bio_bytes = len << inode->i_blkbits;
+
+		xlen -= len;
+		next_block = lblock + len;
+	}
+	if (bio) {
+		if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes)
+				goto add_failed;
+		if (!bio->bi_size)
+			goto dump_bio;
+		
+		submit_bio(WRITE, bio);
+	}
+	if (redirty)
+		redirty_page_for_writepage(wbc, page);
+
+	unlock_page(page);
+
+	return 0;
+add_failed:
+	/* We should never reach here, since we're only adding one vec */
+	printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
+	goto skip;
+dump_bio:
+	dump_mem("bio", bio, sizeof(*bio));
+skip:
+	bio_put(bio);
+	unlock_page(page);
+	dec_io(page, last_write_complete);
+
+	return -EIO;
+}
+
+static int metapage_readpage(struct file *fp, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	struct bio *bio = NULL;
+	unsigned int block_offset;
+	unsigned int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits;
+	sector_t page_start;	/* address of page in fs blocks */
+	sector_t pblock;
+	unsigned int xlen;
+	unsigned int len;
+	unsigned int offset;
+
+	BUG_ON(!PageLocked(page));
+	page_start = (sector_t)page->index <<
+		     (PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+	block_offset = 0;
+	while (block_offset < blocks_per_page) {
+		xlen = blocks_per_page - block_offset;
+		pblock = metapage_get_blocks(inode, page_start + block_offset,
+					     &xlen);
+		if (pblock) {
+			if (!PagePrivate(page))
+				insert_metapage(page, NULL);
+			inc_io(page);
+			if (bio)
+				submit_bio(READ, bio);
+
+			bio = bio_alloc(GFP_NOFS, 1);
+			bio->bi_bdev = inode->i_sb->s_bdev;
+			bio->bi_sector = pblock << (inode->i_blkbits - 9);
+			bio->bi_end_io = metapage_read_end_io;
+			bio->bi_private = page;
+			len = xlen << inode->i_blkbits;
+			offset = block_offset << inode->i_blkbits;
+			if (bio_add_page(bio, page, len, offset) < len)
+				goto add_failed;
+			block_offset += xlen;
+		} else
+			block_offset++;
+	}
+	if (bio)
+		submit_bio(READ, bio);
+	else
+		unlock_page(page);
+
+	return 0;
+
+add_failed:
+	printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
+	bio_put(bio);
+	dec_io(page, last_read_complete);
+	return -EIO;
+}
+
+static int metapage_releasepage(struct page *page, int gfp_mask)
+{
+	struct metapage *mp;
+	int busy = 0;
+	unsigned int offset;
+
+	for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+		mp = page_to_mp(page, offset);
+
+		if (!mp)
+			continue;
+
+		jfs_info("metapage_releasepage: mp = 0x%p", mp);
+		if (mp->count || mp->nohomeok) {
+			jfs_info("count = %ld, nohomeok = %d", mp->count,
+				 mp->nohomeok);
+			busy = 1;
+			continue;
+		}
+		wait_on_page_writeback(page);
+		//WARN_ON(test_bit(META_dirty, &mp->flag));
+		if (test_bit(META_dirty, &mp->flag)) {
+			dump_mem("dirty mp in metapage_releasepage", mp,
+				 sizeof(struct metapage));
+			dump_mem("page", page, sizeof(struct page));
+			dump_stack();
+		}
+		WARN_ON(mp->lsn);
+		if (mp->lsn)
+			remove_from_logsync(mp);
+		remove_metapage(page, mp);
+		INCREMENT(mpStat.pagefree);
+		free_metapage(mp);
+	}
+	if (busy)
+		return -1;
+
+	return 0;
+}
+
+static int metapage_invalidatepage(struct page *page, unsigned long offset)
+{
+	BUG_ON(offset);
+
+	if (PageWriteback(page))
+		return 0;
+
+	return metapage_releasepage(page, 0);
+}
+
+struct address_space_operations jfs_metapage_aops = {
+	.readpage	= metapage_readpage,
+	.writepage	= metapage_writepage,
+	.sync_page	= block_sync_page,
+	.releasepage	= metapage_releasepage,
+	.invalidatepage	= metapage_invalidatepage,
+	.set_page_dirty	= __set_page_dirty_nobuffers,
+};
+
 struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
 				unsigned int size, int absolute,
 				unsigned long new)
 {
-	struct metapage **hash_ptr;
 	int l2BlocksPerPage;
 	int l2bsize;
 	struct address_space *mapping;
-	struct metapage *mp;
+	struct metapage *mp = NULL;
+	struct page *page;
 	unsigned long page_index;
 	unsigned long page_offset;
 
-	jfs_info("__get_metapage: inode = 0x%p, lblock = 0x%lx", inode, lblock);
+	jfs_info("__get_metapage: ino = %ld, lblock = 0x%lx, abs=%d",
+		 inode->i_ino, lblock, absolute);
 
+	l2bsize = inode->i_blkbits;
+	l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
+	page_index = lblock >> l2BlocksPerPage;
+	page_offset = (lblock - (page_index << l2BlocksPerPage)) << l2bsize;
+	if ((page_offset + size) > PAGE_CACHE_SIZE) {
+		jfs_err("MetaData crosses page boundary!!");
+		jfs_err("lblock = %lx, size  = %d", lblock, size);
+		dump_stack();
+		return NULL;
+	}
 	if (absolute)
-		mapping = inode->i_sb->s_bdev->bd_inode->i_mapping;
+		mapping = JFS_SBI(inode->i_sb)->direct_inode->i_mapping;
 	else {
 		/*
 		 * If an nfs client tries to read an inode that is larger
@@ -237,312 +631,212 @@
 		mapping = inode->i_mapping;
 	}
 
-	hash_ptr = meta_hash(mapping, lblock);
-again:
-	spin_lock(&meta_lock);
-	mp = search_hash(hash_ptr, mapping, lblock);
+	if (new && (PSIZE == PAGE_CACHE_SIZE)) {
+		page = grab_cache_page(mapping, page_index);
+		if (!page) {
+			jfs_err("grab_cache_page failed!");
+			return NULL;
+		}
+		SetPageUptodate(page);
+	} else {
+		page = read_cache_page(mapping, page_index,
+			    (filler_t *)mapping->a_ops->readpage, NULL);
+		if (IS_ERR(page)) {
+			jfs_err("read_cache_page failed!");
+			return NULL;
+		}
+		lock_page(page);
+	}
+
+	mp = page_to_mp(page, page_offset);
 	if (mp) {
-	      page_found:
-		if (test_bit(META_stale, &mp->flag)) {
-			spin_unlock(&meta_lock);
-			msleep(1);
-			goto again;
+		if (mp->logical_size != size) {
+			jfs_error(inode->i_sb,
+				  "__get_metapage: mp->logical_size != size");
+			jfs_err("logical_size = %d, size = %d",
+				mp->logical_size, size);
+			dump_stack();
+			goto unlock; 
 		}
 		mp->count++;
 		lock_metapage(mp);
-		spin_unlock(&meta_lock);
 		if (test_bit(META_discard, &mp->flag)) {
 			if (!new) {
 				jfs_error(inode->i_sb,
 					  "__get_metapage: using a "
 					  "discarded metapage");
-				release_metapage(mp);
-				return NULL;
+				discard_metapage(mp);
+				goto unlock; 
 			}
 			clear_bit(META_discard, &mp->flag);
 		}
-		jfs_info("__get_metapage: found 0x%p, in hash", mp);
-		if (mp->logical_size != size) {
-			jfs_error(inode->i_sb,
-				  "__get_metapage: mp->logical_size != size");
-			release_metapage(mp);
-			return NULL;
-		}
 	} else {
-		l2bsize = inode->i_blkbits;
-		l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
-		page_index = lblock >> l2BlocksPerPage;
-		page_offset = (lblock - (page_index << l2BlocksPerPage)) <<
-		    l2bsize;
-		if ((page_offset + size) > PAGE_CACHE_SIZE) {
-			spin_unlock(&meta_lock);
-			jfs_err("MetaData crosses page boundary!!");
-			return NULL;
-		}
-		
-		/*
-		 * Locks held on aggregate inode pages are usually
-		 * not held long, and they are taken in critical code
-		 * paths (committing dirty inodes, txCommit thread) 
-		 * 
-		 * Attempt to get metapage without blocking, tapping into
-		 * reserves if necessary.
-		 */
-		mp = NULL;
-		if (JFS_IP(inode)->fileset == AGGREGATE_I) {
-			mp = alloc_metapage(GFP_ATOMIC);
-			if (!mp) {
-				/*
-				 * mempool is supposed to protect us from
-				 * failing here.  We will try a blocking
-				 * call, but a deadlock is possible here
-				 */
-				printk(KERN_WARNING
-				       "__get_metapage: atomic call to mempool_alloc failed.\n");
-				printk(KERN_WARNING
-				       "Will attempt blocking call\n");
-			}
-		}
-		if (!mp) {
-			struct metapage *mp2;
-
-			spin_unlock(&meta_lock);
-			mp = alloc_metapage(GFP_NOFS);
-			spin_lock(&meta_lock);
-
-			/* we dropped the meta_lock, we need to search the
-			 * hash again.
-			 */
-			mp2 = search_hash(hash_ptr, mapping, lblock);
-			if (mp2) {
-				free_metapage(mp);
-				mp = mp2;
-				goto page_found;
-			}
-		}
+		INCREMENT(mpStat.pagealloc);
+		mp = alloc_metapage(GFP_NOFS);
+		mp->page = page;
 		mp->flag = 0;
-		lock_metapage(mp);
-		if (absolute)
-			set_bit(META_absolute, &mp->flag);
 		mp->xflag = COMMIT_PAGE;
 		mp->count = 1;
-		atomic_set(&mp->nohomeok,0);
-		mp->mapping = mapping;
-		mp->index = lblock;
-		mp->page = NULL;
+		mp->nohomeok = 0;
 		mp->logical_size = size;
-		add_to_hash(mp, hash_ptr);
-		spin_unlock(&meta_lock);
-
-		if (new) {
-			jfs_info("__get_metapage: Calling grab_cache_page");
-			mp->page = grab_cache_page(mapping, page_index);
-			if (!mp->page) {
-				jfs_err("grab_cache_page failed!");
-				goto freeit;
-			} else {
-				INCREMENT(mpStat.pagealloc);
-				unlock_page(mp->page);
-			}
-		} else {
-			jfs_info("__get_metapage: Calling read_cache_page");
-			mp->page = read_cache_page(mapping, lblock,
-				    (filler_t *)mapping->a_ops->readpage, NULL);
-			if (IS_ERR(mp->page)) {
-				jfs_err("read_cache_page failed!");
-				goto freeit;
-			} else
-				INCREMENT(mpStat.pagealloc);
+		mp->data = page_address(page) + page_offset;
+		mp->index = lblock;
+		if (unlikely(insert_metapage(page, mp))) {
+			free_metapage(mp);
+			goto unlock;
 		}
-		mp->data = kmap(mp->page) + page_offset;
+		lock_metapage(mp);
 	}
 
-	if (new)
+	if (new) {
+		jfs_info("zeroing mp = 0x%p", mp);
 		memset(mp->data, 0, PSIZE);
+	}
 
-	jfs_info("__get_metapage: returning = 0x%p", mp);
+	unlock_page(page);
+	jfs_info("__get_metapage: returning = 0x%p data = 0x%p", mp, mp->data);
 	return mp;
 
-freeit:
-	spin_lock(&meta_lock);
-	remove_from_hash(mp, hash_ptr);
-	free_metapage(mp);
-	spin_unlock(&meta_lock);
+unlock:
+	unlock_page(page);
 	return NULL;
 }
 
-void hold_metapage(struct metapage * mp, int force)
+void grab_metapage(struct metapage * mp)
 {
-	spin_lock(&meta_lock);
-
-	mp->count++;
-
-	if (force) {
-		ASSERT (!(test_bit(META_forced, &mp->flag)));
-		if (trylock_metapage(mp))
-			set_bit(META_forced, &mp->flag);
-	} else
-		lock_metapage(mp);
-
-	spin_unlock(&meta_lock);
-}
-
-static void __write_metapage(struct metapage * mp)
-{
-	int l2bsize = mp->mapping->host->i_blkbits;
-	int l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
-	unsigned long page_index;
-	unsigned long page_offset;
-	int rc;
-
-	jfs_info("__write_metapage: mp = 0x%p", mp);
-
-	page_index = mp->page->index;
-	page_offset =
-	    (mp->index - (page_index << l2BlocksPerPage)) << l2bsize;
-
+	jfs_info("grab_metapage: mp = 0x%p", mp);
+	page_cache_get(mp->page);
 	lock_page(mp->page);
-	rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset,
-					       page_offset +
-					       mp->logical_size);
-	if (rc) {
-		jfs_err("prepare_write return %d!", rc);
-		ClearPageUptodate(mp->page);
-		unlock_page(mp->page);
-		clear_bit(META_dirty, &mp->flag);
-		return;
-	}
-	rc = mp->mapping->a_ops->commit_write(NULL, mp->page, page_offset,
-					      page_offset +
-					      mp->logical_size);
-	if (rc) {
-		jfs_err("commit_write returned %d", rc);
-	}
-
+	mp->count++;
+	lock_metapage(mp);
 	unlock_page(mp->page);
-	clear_bit(META_dirty, &mp->flag);
-
-	jfs_info("__write_metapage done");
 }
 
-static inline void sync_metapage(struct metapage *mp)
+void force_metapage(struct metapage *mp)
 {
 	struct page *page = mp->page;
-
+	jfs_info("force_metapage: mp = 0x%p", mp);
+	set_bit(META_forcewrite, &mp->flag);
+	clear_bit(META_sync, &mp->flag);
 	page_cache_get(page);
 	lock_page(page);
-
-	/* we're done with this page - no need to check for errors */
-	if (page_has_buffers(page))
-		write_one_page(page, 1);
-	else
-		unlock_page(page);
+	set_page_dirty(page);
+	write_one_page(page, 1);
+	clear_bit(META_forcewrite, &mp->flag);
 	page_cache_release(page);
 }
 
+extern void hold_metapage(struct metapage *mp)
+{
+	lock_page(mp->page);
+}
+
+extern void put_metapage(struct metapage *mp)
+{
+	if (mp->count || mp->nohomeok) {
+		/* Someone else will release this */
+		unlock_page(mp->page);
+		return;
+	}
+	page_cache_get(mp->page);
+	mp->count++;
+	lock_metapage(mp);
+	unlock_page(mp->page);
+	release_metapage(mp);
+}
+
 void release_metapage(struct metapage * mp)
 {
-	struct jfs_log *log;
-
+	struct page *page = mp->page;
 	jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag);
 
-	spin_lock(&meta_lock);
-	if (test_bit(META_forced, &mp->flag)) {
-		clear_bit(META_forced, &mp->flag);
-		mp->count--;
-		spin_unlock(&meta_lock);
-		return;
-	}
+	BUG_ON(!page);
+
+	lock_page(page);
+	unlock_metapage(mp);
 
 	assert(mp->count);
-	if (--mp->count || atomic_read(&mp->nohomeok)) {
-		unlock_metapage(mp);
-		spin_unlock(&meta_lock);
+	if (--mp->count || mp->nohomeok) {
+		unlock_page(page);
+		page_cache_release(page);
 		return;
 	}
 
-	if (mp->page) {
-		set_bit(META_stale, &mp->flag);
-		spin_unlock(&meta_lock);
-		kunmap(mp->page);
-		mp->data = NULL;
-		if (test_bit(META_dirty, &mp->flag))
-			__write_metapage(mp);
+	if (test_bit(META_dirty, &mp->flag)) {
+		set_page_dirty(page);
 		if (test_bit(META_sync, &mp->flag)) {
-			sync_metapage(mp);
 			clear_bit(META_sync, &mp->flag);
+			write_one_page(page, 1);
+			lock_page(page); /* write_one_page unlocks the page */
 		}
+	} else if (mp->lsn)	/* discard_metapage doesn't remove it */
+		remove_from_logsync(mp);
 
-		if (test_bit(META_discard, &mp->flag)) {
-			lock_page(mp->page);
-			block_invalidatepage(mp->page, 0);
-			unlock_page(mp->page);
+#if MPS_PER_PAGE == 1
+	/*
+	 * If we know this is the only thing in the page, we can throw
+	 * the page out of the page cache.  If pages are larger, we
+	 * don't want to do this.
+	 */
+
+	/* Retest mp->count since we may have released page lock */
+	if (test_bit(META_discard, &mp->flag) && !mp->count) {
+		clear_page_dirty(page);
+		ClearPageUptodate(page);
+#ifdef _NOT_YET
+		if (page->mapping) {
+		/* Remove from page cache and page cache reference */
+			remove_from_page_cache(page);
+			page_cache_release(page);
+			metapage_releasepage(page, 0);
 		}
-
-		page_cache_release(mp->page);
-		mp->page = NULL;
-		INCREMENT(mpStat.pagefree);
-		spin_lock(&meta_lock);
+#endif
 	}
-
-	if (mp->lsn) {
-		/*
-		 * Remove metapage from logsynclist.
-		 */
-		log = mp->log;
-		LOGSYNC_LOCK(log);
-		mp->log = NULL;
-		mp->lsn = 0;
-		mp->clsn = 0;
-		log->count--;
-		list_del(&mp->synclist);
-		LOGSYNC_UNLOCK(log);
-	}
-	remove_from_hash(mp, meta_hash(mp->mapping, mp->index));
-	spin_unlock(&meta_lock);
-
-	free_metapage(mp);
+#else
+	/* Try to keep metapages from using up too much memory */
+	drop_metapage(page, mp);
+#endif
+	unlock_page(page);
+	page_cache_release(page);
 }
 
 void __invalidate_metapages(struct inode *ip, s64 addr, int len)
 {
-	struct metapage **hash_ptr;
-	unsigned long lblock;
+	sector_t lblock;
 	int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits;
+	int BlocksPerPage = 1 << l2BlocksPerPage;
 	/* All callers are interested in block device's mapping */
-	struct address_space *mapping = ip->i_sb->s_bdev->bd_inode->i_mapping;
+	struct address_space *mapping =
+		JFS_SBI(ip->i_sb)->direct_inode->i_mapping;
 	struct metapage *mp;
 	struct page *page;
+	unsigned int offset;
 
 	/*
-	 * First, mark metapages to discard.  They will eventually be
+	 * Mark metapages to discard.  They will eventually be
 	 * released, but should not be written.
 	 */
-	for (lblock = addr; lblock < addr + len;
-	     lblock += 1 << l2BlocksPerPage) {
-		hash_ptr = meta_hash(mapping, lblock);
-again:
-		spin_lock(&meta_lock);
-		mp = search_hash(hash_ptr, mapping, lblock);
-		if (mp) {
-			if (test_bit(META_stale, &mp->flag)) {
-				spin_unlock(&meta_lock);
-				msleep(1);
-				goto again;
-			}
+	for (lblock = addr & ~(BlocksPerPage - 1); lblock < addr + len;
+	     lblock += BlocksPerPage) {
+		page = find_lock_page(mapping, lblock >> l2BlocksPerPage);
+		if (!page)
+			continue;
+		for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+			mp = page_to_mp(page, offset);
+			if (!mp)
+				continue;
+			if (mp->index < addr)
+				continue;
+			if (mp->index >= addr + len)
+				break;
 
 			clear_bit(META_dirty, &mp->flag);
 			set_bit(META_discard, &mp->flag);
-			spin_unlock(&meta_lock);
-		} else {
-			spin_unlock(&meta_lock);
-			page = find_lock_page(mapping, lblock>>l2BlocksPerPage);
-			if (page) {
-				block_invalidatepage(page, 0);
-				unlock_page(page);
-				page_cache_release(page);
-			}
+			if (mp->lsn)
+				remove_from_logsync(mp);
 		}
+		unlock_page(page);
+		page_cache_release(page);
 	}
 }
 
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 0e58aba..991e9fb 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -33,38 +33,27 @@
 	unsigned long flag;	/* See Below */
 	unsigned long count;	/* Reference count */
 	void *data;		/* Data pointer */
-
-	/* list management stuff */
-	struct metapage *hash_prev;
-	struct metapage *hash_next;	/* Also used for free list */
-
-	/*
-	 * mapping & index become redundant, but we need these here to
-	 * add the metapage to the hash before we have the real page
-	 */
-	struct address_space *mapping;
-	unsigned long index;
+	sector_t index; 	/* block address of page */
 	wait_queue_head_t wait;
 
 	/* implementation */
 	struct page *page;
-	unsigned long logical_size;
+	unsigned int logical_size;
 
 	/* Journal management */
 	int clsn;
-	atomic_t nohomeok;
+	int nohomeok;
 	struct jfs_log *log;
 };
 
 /* metapage flag */
 #define META_locked	0
-#define META_absolute	1
-#define META_free	2
-#define META_dirty	3
-#define META_sync	4
-#define META_discard	5
-#define META_forced	6
-#define META_stale	7
+#define META_free	1
+#define META_dirty	2
+#define META_sync	3
+#define META_discard	4
+#define META_forcewrite	5
+#define META_io		6
 
 #define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
 
@@ -80,7 +69,16 @@
 	 __get_metapage(inode, lblock, size, absolute, TRUE)
 
 extern void release_metapage(struct metapage *);
-extern void hold_metapage(struct metapage *, int);
+extern void grab_metapage(struct metapage *);
+extern void force_metapage(struct metapage *);
+
+/*
+ * hold_metapage and put_metapage are used in conjuction.  The page lock
+ * is not dropped between the two, so no other threads can get or release
+ * the metapage
+ */
+extern void hold_metapage(struct metapage *);
+extern void put_metapage(struct metapage *);
 
 static inline void write_metapage(struct metapage *mp)
 {
@@ -101,6 +99,46 @@
 	release_metapage(mp);
 }
 
+static inline void metapage_nohomeok(struct metapage *mp)
+{
+	struct page *page = mp->page;
+	lock_page(page);
+	if (!mp->nohomeok++) {
+		mark_metapage_dirty(mp);
+		page_cache_get(page);
+		wait_on_page_writeback(page);
+	}
+	unlock_page(page);
+}
+
+/*
+ * This serializes access to mp->lsn when metapages are added to logsynclist
+ * without setting nohomeok.  i.e. updating imap & dmap
+ */
+static inline void metapage_wait_for_io(struct metapage *mp)
+{
+	if (test_bit(META_io, &mp->flag))
+		wait_on_page_writeback(mp->page);
+}
+
+/*
+ * This is called when already holding the metapage
+ */
+static inline void _metapage_homeok(struct metapage *mp)
+{
+	if (!--mp->nohomeok)
+		page_cache_release(mp->page);
+}
+
+static inline void metapage_homeok(struct metapage *mp)
+{
+	hold_metapage(mp);
+	_metapage_homeok(mp);
+	put_metapage(mp);
+}
+
+extern struct address_space_operations jfs_metapage_aops;
+
 /*
  * This routines invalidate all pages for an extent.
  */
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index c535ffd..032d111 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -285,11 +285,6 @@
 	 */
 	logMOUNT(sb);
 
-	/*
-	 * Set page cache allocation policy
-	 */
-	mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
-
 	return rc;
 }
 
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f40301d..e93d01a 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -227,6 +227,7 @@
 
 static void txLockFree(lid_t lid)
 {
+	TxLock[lid].tid = 0;
 	TxLock[lid].next = TxAnchor.freelock;
 	TxAnchor.freelock = lid;
 	TxAnchor.tlocksInUse--;
@@ -566,9 +567,6 @@
 		 * synchronize with logsync barrier
 		 */
 		if (test_bit(log_SYNCBARRIER, &log->flag)) {
-			/* forward log syncpt */
-			/* lmSync(log); */
-
 			jfs_info("log barrier off: 0x%x", log->lsn);
 
 			/* enable new transactions start */
@@ -576,15 +574,22 @@
 
 			/* wakeup all waitors for logsync barrier */
 			TXN_WAKEUP(&log->syncwait);
+
+			TXN_UNLOCK();
+
+			/* forward log syncpt */
+			jfs_syncpt(log);
+
+			goto wakeup;
 		}
 	}
 
+	TXN_UNLOCK();
+wakeup:
 	/*
 	 * wakeup all waitors for a free tblock
 	 */
 	TXN_WAKEUP(&TxAnchor.freewait);
-
-	TXN_UNLOCK();
 }
 
 
@@ -633,8 +638,10 @@
 
 	/* is page locked by the requester transaction ? */
 	tlck = lid_to_tlock(lid);
-	if ((xtid = tlck->tid) == tid)
+	if ((xtid = tlck->tid) == tid) {
+		TXN_UNLOCK();
 		goto grantLock;
+	}
 
 	/*
 	 * is page locked by anonymous transaction/lock ?
@@ -649,6 +656,7 @@
 	 */
 	if (xtid == 0) {
 		tlck->tid = tid;
+		TXN_UNLOCK();
 		tblk = tid_to_tblock(tid);
 		/*
 		 * The order of the tlocks in the transaction is important
@@ -706,17 +714,18 @@
 	 */
 	tlck->tid = tid;
 
+	TXN_UNLOCK();
+
 	/* mark tlock for meta-data page */
 	if (mp->xflag & COMMIT_PAGE) {
 
 		tlck->flag = tlckPAGELOCK;
 
 		/* mark the page dirty and nohomeok */
-		mark_metapage_dirty(mp);
-		atomic_inc(&mp->nohomeok);
+		metapage_nohomeok(mp);
 
 		jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
-			 mp, atomic_read(&mp->nohomeok), tid, tlck);
+			 mp, mp->nohomeok, tid, tlck);
 
 		/* if anonymous transaction, and buffer is on the group
 		 * commit synclist, mark inode to show this.  This will
@@ -762,8 +771,10 @@
 		if (tlck->next == 0) {
 			/* This inode's first anonymous transaction */
 			jfs_ip->atltail = lid;
+			TXN_LOCK();
 			list_add_tail(&jfs_ip->anon_inode_list,
 				      &TxAnchor.anon_list);
+			TXN_UNLOCK();
 		}
 	}
 
@@ -821,8 +832,6 @@
       grantLock:
 	tlck->type |= type;
 
-	TXN_UNLOCK();
-
 	return tlck;
 
 	/*
@@ -841,11 +850,19 @@
 		BUG();
 	}
 	INCREMENT(stattx.waitlock);	/* statistics */
+	TXN_UNLOCK();
 	release_metapage(mp);
+	TXN_LOCK();
+	xtid = tlck->tid;	/* reaquire after dropping TXN_LOCK */
 
 	jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
 		 tid, xtid, lid);
-	TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
+
+	/* Recheck everything since dropping TXN_LOCK */
+	if (xtid && (tlck->mp == mp) && (mp->lid == lid))
+		TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
+	else
+		TXN_UNLOCK();
 	jfs_info("txLock: awakened     tid = %d, lid = %d", tid, lid);
 
 	return NULL;
@@ -906,6 +923,7 @@
 	struct metapage *mp;
 	struct jfs_log *log;
 	int difft, diffp;
+	unsigned long flags;
 
 	jfs_info("txUnlock: tblk = 0x%p", tblk);
 	log = JFS_SBI(tblk->sb)->log;
@@ -925,19 +943,14 @@
 			assert(mp->xflag & COMMIT_PAGE);
 
 			/* hold buffer
-			 *
-			 * It's possible that someone else has the metapage.
-			 * The only things were changing are nohomeok, which
-			 * is handled atomically, and clsn which is protected
-			 * by the LOGSYNC_LOCK.
 			 */
-			hold_metapage(mp, 1);
+			hold_metapage(mp);
 
-			assert(atomic_read(&mp->nohomeok) > 0);
-			atomic_dec(&mp->nohomeok);
+			assert(mp->nohomeok > 0);
+			_metapage_homeok(mp);
 
 			/* inherit younger/larger clsn */
-			LOGSYNC_LOCK(log);
+			LOGSYNC_LOCK(log, flags);
 			if (mp->clsn) {
 				logdiff(difft, tblk->clsn, log);
 				logdiff(diffp, mp->clsn, log);
@@ -945,16 +958,11 @@
 					mp->clsn = tblk->clsn;
 			} else
 				mp->clsn = tblk->clsn;
-			LOGSYNC_UNLOCK(log);
+			LOGSYNC_UNLOCK(log, flags);
 
 			assert(!(tlck->flag & tlckFREEPAGE));
 
-			if (tlck->flag & tlckWRITEPAGE) {
-				write_metapage(mp);
-			} else {
-				/* release page which has been forced */
-				release_metapage(mp);
-			}
+			put_metapage(mp);
 		}
 
 		/* insert tlock, and linelock(s) of the tlock if any,
@@ -981,10 +989,10 @@
 	 * has been inserted in logsync list at txUpdateMap())
 	 */
 	if (tblk->lsn) {
-		LOGSYNC_LOCK(log);
+		LOGSYNC_LOCK(log, flags);
 		log->count--;
 		list_del(&tblk->synclist);
-		LOGSYNC_UNLOCK(log);
+		LOGSYNC_UNLOCK(log, flags);
 	}
 }
 
@@ -1573,8 +1581,8 @@
 		 * the last entry, so don't bother logging this
 		 */
 		mp->lid = 0;
-		hold_metapage(mp, 0);
-		atomic_dec(&mp->nohomeok);
+		grab_metapage(mp);
+		metapage_homeok(mp);
 		discard_metapage(mp);
 		tlck->mp = NULL;
 		return 0;
@@ -1712,7 +1720,7 @@
 	struct maplock *maplock;
 	struct xdlistlock *xadlock;
 	struct pxd_lock *pxdlock;
-	pxd_t *pxd;
+	pxd_t *page_pxd;
 	int next, lwm, hwm;
 
 	ip = tlck->ip;
@@ -1722,7 +1730,7 @@
 	lrd->log.redopage.type = cpu_to_le16(LOG_XTREE);
 	lrd->log.redopage.l2linesize = cpu_to_le16(L2XTSLOTSIZE);
 
-	pxd = &lrd->log.redopage.pxd;
+	page_pxd = &lrd->log.redopage.pxd;
 
 	if (tlck->type & tlckBTROOT) {
 		lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
@@ -1752,9 +1760,9 @@
 		 * applying the after-image to the meta-data page.
 		 */
 		lrd->type = cpu_to_le16(LOG_REDOPAGE);
-//              *pxd = mp->cm_pxd;
-		PXDaddress(pxd, mp->index);
-		PXDlength(pxd,
+//              *page_pxd = mp->cm_pxd;
+		PXDaddress(page_pxd, mp->index);
+		PXDlength(page_pxd,
 			  mp->logical_size >> tblk->sb->s_blocksize_bits);
 		lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
 
@@ -1776,25 +1784,31 @@
 		tlck->flag |= tlckUPDATEMAP;
 		xadlock->flag = mlckALLOCXADLIST;
 		xadlock->count = next - lwm;
-		if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) {
+		if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
 			int i;
+			pxd_t *pxd;
 			/*
 			 * Lazy commit may allow xtree to be modified before
 			 * txUpdateMap runs.  Copy xad into linelock to
 			 * preserve correct data.
+			 *
+			 * We can fit twice as may pxd's as xads in the lock
 			 */
-			xadlock->xdlist = &xtlck->pxdlock;
-			memcpy(xadlock->xdlist, &p->xad[lwm],
-			       sizeof(xad_t) * xadlock->count);
-
-			for (i = 0; i < xadlock->count; i++)
+			xadlock->flag = mlckALLOCPXDLIST;
+			pxd = xadlock->xdlist = &xtlck->pxdlock;
+			for (i = 0; i < xadlock->count; i++) {
+				PXDaddress(pxd, addressXAD(&p->xad[lwm + i]));
+				PXDlength(pxd, lengthXAD(&p->xad[lwm + i]));
 				p->xad[lwm + i].flag &=
 				    ~(XAD_NEW | XAD_EXTENDED);
+				pxd++;
+			}
 		} else {
 			/*
 			 * xdlist will point to into inode's xtree, ensure
 			 * that transaction is not committed lazily.
 			 */
+			xadlock->flag = mlckALLOCXADLIST;
 			xadlock->xdlist = &p->xad[lwm];
 			tblk->xflag &= ~COMMIT_LAZY;
 		}
@@ -1836,8 +1850,8 @@
 		if (tblk->xflag & COMMIT_TRUNCATE) {
 			/* write NOREDOPAGE for the page */
 			lrd->type = cpu_to_le16(LOG_NOREDOPAGE);
-			PXDaddress(pxd, mp->index);
-			PXDlength(pxd,
+			PXDaddress(page_pxd, mp->index);
+			PXDlength(page_pxd,
 				  mp->logical_size >> tblk->sb->
 				  s_blocksize_bits);
 			lrd->backchain =
@@ -1872,22 +1886,32 @@
 		 * deleted page itself;
 		 */
 		tlck->flag |= tlckUPDATEMAP;
-		xadlock->flag = mlckFREEXADLIST;
 		xadlock->count = hwm - XTENTRYSTART + 1;
-		if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) {
+		if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
+			int i;
+			pxd_t *pxd;
 			/*
 			 * Lazy commit may allow xtree to be modified before
 			 * txUpdateMap runs.  Copy xad into linelock to
 			 * preserve correct data.
+			 *
+			 * We can fit twice as may pxd's as xads in the lock
 			 */
-			xadlock->xdlist = &xtlck->pxdlock;
-			memcpy(xadlock->xdlist, &p->xad[XTENTRYSTART],
-			       sizeof(xad_t) * xadlock->count);
+			xadlock->flag = mlckFREEPXDLIST;
+			pxd = xadlock->xdlist = &xtlck->pxdlock;
+			for (i = 0; i < xadlock->count; i++) {
+				PXDaddress(pxd,
+					addressXAD(&p->xad[XTENTRYSTART + i]));
+				PXDlength(pxd,
+					lengthXAD(&p->xad[XTENTRYSTART + i]));
+				pxd++;
+			}
 		} else {
 			/*
 			 * xdlist will point to into inode's xtree, ensure
 			 * that transaction is not committed lazily.
 			 */
+			xadlock->flag = mlckFREEXADLIST;
 			xadlock->xdlist = &p->xad[XTENTRYSTART];
 			tblk->xflag &= ~COMMIT_LAZY;
 		}
@@ -1918,7 +1942,7 @@
 	 * header ?
 	 */
 	if (tlck->type & tlckTRUNCATE) {
-		pxd_t tpxd;	/* truncated extent of xad */
+		pxd_t pxd;	/* truncated extent of xad */
 		int twm;
 
 		/*
@@ -1947,8 +1971,9 @@
 		 * applying the after-image to the meta-data page.
 		 */
 		lrd->type = cpu_to_le16(LOG_REDOPAGE);
-		PXDaddress(pxd, mp->index);
-		PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits);
+		PXDaddress(page_pxd, mp->index);
+		PXDlength(page_pxd,
+			  mp->logical_size >> tblk->sb->s_blocksize_bits);
 		lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
 
 		/*
@@ -1966,7 +1991,7 @@
 			lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD);
 			lrd->log.updatemap.nxd = cpu_to_le16(1);
 			lrd->log.updatemap.pxd = pxdlock->pxd;
-			tpxd = pxdlock->pxd;	/* save to format maplock */
+			pxd = pxdlock->pxd;	/* save to format maplock */
 			lrd->backchain =
 			    cpu_to_le32(lmLog(log, tblk, lrd, NULL));
 		}
@@ -2035,7 +2060,7 @@
 			pxdlock = (struct pxd_lock *) xadlock;
 			pxdlock->flag = mlckFREEPXD;
 			pxdlock->count = 1;
-			pxdlock->pxd = tpxd;
+			pxdlock->pxd = pxd;
 
 			jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d "
 				 "hwm:%d", ip, mp, pxdlock->count, hwm);
@@ -2253,7 +2278,8 @@
 				tlck->flag &= ~tlckWRITEPAGE;
 
 				/* do not release page to freelist */
-
+				force_metapage(mp);
+#if 0
 				/*
 				 * The "right" thing to do here is to
 				 * synchronously write the metadata.
@@ -2265,9 +2291,10 @@
 				 * we can get by with synchronously writing
 				 * the pages when they are released.
 				 */
-				assert(atomic_read(&mp->nohomeok));
+				assert(mp->nohomeok);
 				set_bit(META_dirty, &mp->flag);
 				set_bit(META_sync, &mp->flag);
+#endif
 			}
 		}
 	}
@@ -2327,7 +2354,7 @@
 			 */
 			mp = tlck->mp;
 			ASSERT(mp->xflag & COMMIT_PAGE);
-			hold_metapage(mp, 0);
+			grab_metapage(mp);
 		}
 
 		/*
@@ -2377,8 +2404,8 @@
 				ASSERT(mp->lid == lid);
 				tlck->mp->lid = 0;
 			}
-			assert(atomic_read(&mp->nohomeok) == 1);
-			atomic_dec(&mp->nohomeok);
+			assert(mp->nohomeok == 1);
+			metapage_homeok(mp);
 			discard_metapage(mp);
 			tlck->mp = NULL;
 		}
@@ -2844,24 +2871,9 @@
 {
 	struct jfs_log *log = mp->log;
 
-	assert(atomic_read(&mp->nohomeok));
+	assert(mp->nohomeok);
 	assert(log);
-	atomic_dec(&mp->nohomeok);
-
-	if (atomic_read(&mp->nohomeok))
-		return;
-
-	hold_metapage(mp, 0);
-
-	LOGSYNC_LOCK(log);
-	mp->log = NULL;
-	mp->lsn = 0;
-	mp->clsn = 0;
-	log->count--;
-	list_del_init(&mp->synclist);
-	LOGSYNC_UNLOCK(log);
-
-	release_metapage(mp);
+	metapage_homeok(mp);
 }
 
 /*
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index f31a9e3..5cf9178 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -49,7 +49,6 @@
  */
 int jfs_umount(struct super_block *sb)
 {
-	struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	struct inode *ipbmap = sbi->ipbmap;
 	struct inode *ipimap = sbi->ipimap;
@@ -109,8 +108,8 @@
 	 * Make sure all metadata makes it to disk before we mark
 	 * the superblock as clean
 	 */
-	filemap_fdatawrite(bdev_mapping);
-	filemap_fdatawait(bdev_mapping);
+	filemap_fdatawrite(sbi->direct_inode->i_mapping);
+	filemap_fdatawait(sbi->direct_inode->i_mapping);
 
 	/*
 	 * ensure all file system file pages are propagated to their
@@ -123,9 +122,6 @@
 	if (log) {		/* log = NULL if read-only mount */
 		updateSuper(sb, FM_CLEAN);
 
-		/* Restore default gfp_mask for bdev */
-		mapping_set_gfp_mask(bdev_mapping, GFP_USER);
-
 		/*
 		 * close log: 
 		 *
@@ -140,7 +136,6 @@
 
 int jfs_umount_rw(struct super_block *sb)
 {
-	struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	struct jfs_log *log = sbi->log;
 
@@ -166,13 +161,10 @@
 	 * mark the superblock clean before everything is flushed to
 	 * disk.
 	 */
-	filemap_fdatawrite(bdev_mapping);
-	filemap_fdatawait(bdev_mapping);
+	filemap_fdatawrite(sbi->direct_inode->i_mapping);
+	filemap_fdatawait(sbi->direct_inode->i_mapping);
 
 	updateSuper(sb, FM_CLEAN);
 
-	/* Restore default gfp_mask for bdev */
-	mapping_set_gfp_mask(bdev_mapping, GFP_USER);
-
 	return lmLogClose(sb);
 }
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 11c58c5..31b34db 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2004
+ *   Copyright (C) International Business Machines Corp., 2000-2005
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -111,8 +111,8 @@
 /*
  * forward references
  */
-static int xtSearch(struct inode *ip,
-		    s64 xoff, int *cmpp, struct btstack * btstack, int flag);
+static int xtSearch(struct inode *ip, s64 xoff, s64 *next, int *cmpp,
+		    struct btstack * btstack, int flag);
 
 static int xtSplitUp(tid_t tid,
 		     struct inode *ip,
@@ -159,11 +159,12 @@
 	xtpage_t *p;
 	int index;
 	xad_t *xad;
-	s64 size, xoff, xend;
+	s64 next, size, xoff, xend;
 	int xlen;
 	s64 xaddr;
 
-	*plen = 0;
+	*paddr = 0;
+	*plen = llen;
 
 	if (!no_check) {
 		/* is lookup offset beyond eof ? */
@@ -180,7 +181,7 @@
 	 * search for the xad entry covering the logical extent
 	 */
 //search:
-	if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) {
+	if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) {
 		jfs_err("xtLookup: xtSearch returned %d", rc);
 		return rc;
 	}
@@ -198,8 +199,11 @@
 	 * lstart is a page start address,
 	 * i.e., lstart cannot start in a hole;
 	 */
-	if (cmp)
+	if (cmp) {
+		if (next)
+			*plen = min(next - lstart, llen);
 		goto out;
+	}
 
 	/*
 	 * lxd covered by xad
@@ -284,7 +288,7 @@
 	if (lstart >= size)
 		return 0;
 
-	if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0)))
+	if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0)))
 		return rc;
 
 	/*
@@ -488,6 +492,7 @@
  * parameters:
  *      ip      - file object;
  *      xoff    - extent offset;
+ *      nextp	- address of next extent (if any) for search miss
  *      cmpp    - comparison result:
  *      btstack - traverse stack;
  *      flag    - search process flag (XT_INSERT);
@@ -497,7 +502,7 @@
  *      *cmpp is set to result of comparison with the entry returned.
  *      the page containing the entry is pinned at exit.
  */
-static int xtSearch(struct inode *ip, s64 xoff,	/* offset of extent */
+static int xtSearch(struct inode *ip, s64 xoff,	s64 *nextp,
 		    int *cmpp, struct btstack * btstack, int flag)
 {
 	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
@@ -511,6 +516,7 @@
 	struct btframe *btsp;
 	int nsplit = 0;		/* number of pages to split */
 	s64 t64;
+	s64 next = 0;
 
 	INCREMENT(xtStat.search);
 
@@ -579,6 +585,7 @@
 						 * previous and this entry
 						 */
 						*cmpp = 1;
+						next = t64;
 						goto out;
 					}
 
@@ -623,6 +630,9 @@
 			/* update sequential access heuristics */
 			jfs_ip->btindex = index;
 
+			if (nextp)
+				*nextp = next;
+
 			INCREMENT(xtStat.fastSearch);
 			return 0;
 		}
@@ -675,10 +685,11 @@
 
 					return 0;
 				}
-
 				/* search hit - internal page:
 				 * descend/search its child page
 				 */
+				if (index < le16_to_cpu(p->header.nextindex)-1)
+					next = offsetXAD(&p->xad[index + 1]);
 				goto next;
 			}
 
@@ -694,6 +705,8 @@
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or maxentry index.
 		 */
+		if (base < le16_to_cpu(p->header.nextindex))
+			next = offsetXAD(&p->xad[base]);
 		/*
 		 * search miss - leaf page:
 		 *
@@ -727,6 +740,9 @@
 				jfs_ip->btorder = BT_RANDOM;
 			jfs_ip->btindex = base;
 
+			if (nextp)
+				*nextp = next;
+
 			return 0;
 		}
 
@@ -793,6 +809,7 @@
 	struct xtsplit split;	/* split information */
 	xad_t *xad;
 	int cmp;
+	s64 next;
 	struct tlock *tlck;
 	struct xtlock *xtlck;
 
@@ -806,7 +823,7 @@
 	 * n.b. xtSearch() may return index of maxentry of
 	 * the full page.
 	 */
-	if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
+	if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
 		return rc;
 
 	/* retrieve search result */
@@ -814,7 +831,7 @@
 
 	/* This test must follow XT_GETSEARCH since mp must be valid if
 	 * we branch to out: */
-	if (cmp == 0) {
+	if ((cmp == 0) || (next && (xlen > next - xoff))) {
 		rc = -EEXIST;
 		goto out;
 	}
@@ -1626,7 +1643,7 @@
 	jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
 
 	/* there must exist extent to be extended */
-	if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))
+	if ((rc = xtSearch(ip, xoff - 1, NULL, &cmp, &btstack, XT_INSERT)))
 		return rc;
 
 	/* retrieve search result */
@@ -1794,7 +1811,7 @@
 */
 
 	/* there must exist extent to be tailgated */
-	if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
+	if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT)))
 		return rc;
 
 	/* retrieve search result */
@@ -1977,7 +1994,7 @@
 	nxlen = lengthXAD(nxad);
 	nxaddr = addressXAD(nxad);
 
-	if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
+	if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
 		return rc;
 
 	/* retrieve search result */
@@ -2291,7 +2308,7 @@
 	if (nextindex == le16_to_cpu(p->header.maxentry)) {
 		XT_PUTPAGE(mp);
 
-		if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
+		if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
 			return rc;
 
 		/* retrieve search result */
@@ -2438,6 +2455,7 @@
 	int nsplit, nblocks, xlen;
 	struct pxdlist pxdlist;
 	pxd_t *pxd;
+	s64 next;
 
 	xaddr = *xaddrp;
 	xlen = *xlenp;
@@ -2452,7 +2470,7 @@
 	 * n.b. xtSearch() may return index of maxentry of
 	 * the full page.
 	 */
-	if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
+	if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
 		return rc;
 
 	/* retrieve search result */
@@ -2462,6 +2480,9 @@
 		rc = -EEXIST;
 		goto out;
 	}
+
+	if (next)
+		xlen = min(xlen, (int)(next - xoff));
 //insert:
 	/*
 	 *      insert entry for new extent
@@ -2600,7 +2621,7 @@
 	/*
 	 * find the matching entry; xtSearch() pins the page
 	 */
-	if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0)))
+	if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
 		return rc;
 
 	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
@@ -2852,7 +2873,7 @@
 	 */
 	if (xtype == DATAEXT) {
 		/* search in leaf entry */
-		rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
+		rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
 		if (rc)
 			return rc;
 
@@ -2958,7 +2979,7 @@
 		}
 
 		/* get back parent page */
-		if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0)))
+		if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
 			return rc;
 
 		XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
@@ -3991,7 +4012,7 @@
 
 	if (committed_size) {
 		xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1;
-		rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
+		rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
 		if (rc)
 			return rc;
 
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 2eb6869..c6dc254 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -209,6 +209,9 @@
 	 */
 	txQuiesce(sb);
 
+	/* Reset size of direct inode */
+	sbi->direct_inode->i_size =  sb->s_bdev->bd_inode->i_size;
+
 	if (sbi->mntflag & JFS_INLINELOG) {
 		/*
 		 * deactivate old inline log
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5856866..5e774ed 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -210,6 +210,10 @@
 		unload_nls(sbi->nls_tab);
 	sbi->nls_tab = NULL;
 
+	truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
+	iput(sbi->direct_inode);
+	sbi->direct_inode = NULL;
+
 	kfree(sbi);
 }
 
@@ -358,6 +362,12 @@
 	}
 
 	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+		/*
+		 * Invalidate any previously read metadata.  fsck may have
+		 * changed the on-disk data since we mounted r/o
+		 */
+		truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
+
 		JFS_SBI(sb)->flag = flag;
 		return jfs_mount_rw(sb, 1);
 	}
@@ -428,12 +438,26 @@
 	sb->s_op = &jfs_super_operations;
 	sb->s_export_op = &jfs_export_operations;
 
+	/*
+	 * Initialize direct-mapping inode/address-space
+	 */
+	inode = new_inode(sb);
+	if (inode == NULL)
+		goto out_kfree;
+	inode->i_ino = 0;
+	inode->i_nlink = 1;
+	inode->i_size = sb->s_bdev->bd_inode->i_size;
+	inode->i_mapping->a_ops = &jfs_metapage_aops;
+	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
+
+	sbi->direct_inode = inode;
+
 	rc = jfs_mount(sb);
 	if (rc) {
 		if (!silent) {
 			jfs_err("jfs_mount failed w/return code = %d", rc);
 		}
-		goto out_kfree;
+		goto out_mount_failed;
 	}
 	if (sb->s_flags & MS_RDONLY)
 		sbi->log = NULL;
@@ -482,6 +506,13 @@
 	if (rc) {
 		jfs_err("jfs_umount failed with return code %d", rc);
 	}
+out_mount_failed:
+	filemap_fdatawrite(sbi->direct_inode->i_mapping);
+	filemap_fdatawait(sbi->direct_inode->i_mapping);
+	truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
+	make_bad_inode(sbi->direct_inode);
+	iput(sbi->direct_inode);
+	sbi->direct_inode = NULL;
 out_kfree:
 	if (sbi->nls_tab)
 		unload_nls(sbi->nls_tab);
@@ -527,8 +558,10 @@
 	struct jfs_log *log = JFS_SBI(sb)->log;
 
 	/* log == NULL indicates read-only mount */
-	if (log)
+	if (log) {
 		jfs_flush_journal(log, wait);
+		jfs_syncpt(log);
+	}
 
 	return 0;
 }
diff --git a/fs/locks.c b/fs/locks.c
index 1792ce5..3fa6a7c 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -406,12 +406,12 @@
 	fl->fl_file->f_owner.signum = 0;
 }
 
-int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
+static int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
 {
 	return fl->fl_file == try->fl_file;
 }
 
-struct lock_manager_operations lease_manager_ops = {
+static struct lock_manager_operations lease_manager_ops = {
 	.fl_break = lease_break_callback,
 	.fl_release_private = lease_release_private_callback,
 	.fl_mylease = lease_mylease_callback,
@@ -1274,7 +1274,7 @@
  *
  *	Called with kernel lock held.
  */
-int __setlease(struct file *filp, long arg, struct file_lock **flp)
+static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 {
 	struct file_lock *fl, **before, **my_before = NULL, *lease = *flp;
 	struct dentry *dentry = filp->f_dentry;
diff --git a/fs/mbcache.c b/fs/mbcache.c
index f9e4d27..c7170b9 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -57,7 +57,7 @@
 
 #define MB_CACHE_WRITER ((unsigned short)~0U >> 1)
 
-DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue);
+static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue);
 		
 MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
 MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
diff --git a/fs/mpage.c b/fs/mpage.c
index e7d8d1a..b92c0e6 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -87,7 +87,7 @@
 	return 0;
 }
 
-struct bio *mpage_bio_submit(int rw, struct bio *bio)
+static struct bio *mpage_bio_submit(int rw, struct bio *bio)
 {
 	bio->bi_end_io = mpage_end_io_read;
 	if (rw == WRITE)
@@ -160,52 +160,6 @@
 	} while (page_bh != head);
 }
 
-/**
- * mpage_readpages - populate an address space with some pages, and
- *                       start reads against them.
- *
- * @mapping: the address_space
- * @pages: The address of a list_head which contains the target pages.  These
- *   pages have their ->index populated and are otherwise uninitialised.
- *
- *   The page at @pages->prev has the lowest file offset, and reads should be
- *   issued in @pages->prev to @pages->next order.
- *
- * @nr_pages: The number of pages at *@pages
- * @get_block: The filesystem's block mapper function.
- *
- * This function walks the pages and the blocks within each page, building and
- * emitting large BIOs.
- *
- * If anything unusual happens, such as:
- *
- * - encountering a page which has buffers
- * - encountering a page which has a non-hole after a hole
- * - encountering a page with non-contiguous blocks
- *
- * then this code just gives up and calls the buffer_head-based read function.
- * It does handle a page which has holes at the end - that is a common case:
- * the end-of-file on blocksize < PAGE_CACHE_SIZE setups.
- *
- * BH_Boundary explanation:
- *
- * There is a problem.  The mpage read code assembles several pages, gets all
- * their disk mappings, and then submits them all.  That's fine, but obtaining
- * the disk mappings may require I/O.  Reads of indirect blocks, for example.
- *
- * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be
- * submitted in the following order:
- * 	12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16
- * because the indirect block has to be read to get the mappings of blocks
- * 13,14,15,16.  Obviously, this impacts performance.
- * 
- * So what we do it to allow the filesystem's get_block() function to set
- * BH_Boundary when it maps block 11.  BH_Boundary says: mapping of the block
- * after this one will require I/O against a block which is probably close to
- * this one.  So you should push what I/O you have currently accumulated.
- *
- * This all causes the disk requests to be issued in the correct order.
- */
 static struct bio *
 do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
 			sector_t *last_block_in_bio, get_block_t get_block)
@@ -320,6 +274,52 @@
 	goto out;
 }
 
+/**
+ * mpage_readpages - populate an address space with some pages, and
+ *                       start reads against them.
+ *
+ * @mapping: the address_space
+ * @pages: The address of a list_head which contains the target pages.  These
+ *   pages have their ->index populated and are otherwise uninitialised.
+ *
+ *   The page at @pages->prev has the lowest file offset, and reads should be
+ *   issued in @pages->prev to @pages->next order.
+ *
+ * @nr_pages: The number of pages at *@pages
+ * @get_block: The filesystem's block mapper function.
+ *
+ * This function walks the pages and the blocks within each page, building and
+ * emitting large BIOs.
+ *
+ * If anything unusual happens, such as:
+ *
+ * - encountering a page which has buffers
+ * - encountering a page which has a non-hole after a hole
+ * - encountering a page with non-contiguous blocks
+ *
+ * then this code just gives up and calls the buffer_head-based read function.
+ * It does handle a page which has holes at the end - that is a common case:
+ * the end-of-file on blocksize < PAGE_CACHE_SIZE setups.
+ *
+ * BH_Boundary explanation:
+ *
+ * There is a problem.  The mpage read code assembles several pages, gets all
+ * their disk mappings, and then submits them all.  That's fine, but obtaining
+ * the disk mappings may require I/O.  Reads of indirect blocks, for example.
+ *
+ * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be
+ * submitted in the following order:
+ * 	12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16
+ * because the indirect block has to be read to get the mappings of blocks
+ * 13,14,15,16.  Obviously, this impacts performance.
+ *
+ * So what we do it to allow the filesystem's get_block() function to set
+ * BH_Boundary when it maps block 11.  BH_Boundary says: mapping of the block
+ * after this one will require I/O against a block which is probably close to
+ * this one.  So you should push what I/O you have currently accumulated.
+ *
+ * This all causes the disk requests to be issued in the correct order.
+ */
 int
 mpage_readpages(struct address_space *mapping, struct list_head *pages,
 				unsigned nr_pages, get_block_t get_block)
@@ -627,15 +627,6 @@
 mpage_writepages(struct address_space *mapping,
 		struct writeback_control *wbc, get_block_t get_block)
 {
-	return __mpage_writepages(mapping, wbc, get_block,
-		mapping->a_ops->writepage);
-}
-
-int
-__mpage_writepages(struct address_space *mapping,
-		struct writeback_control *wbc, get_block_t get_block,
-		writepage_t writepage_fn)
-{
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	struct bio *bio = NULL;
 	sector_t last_block_in_bio = 0;
@@ -725,8 +716,10 @@
 			} else {
 				bio = __mpage_writepage(bio, page, get_block,
 						&last_block_in_bio, &ret, wbc,
-						writepage_fn);
+						page->mapping->a_ops->writepage);
 			}
+			if (unlikely(ret == WRITEPAGE_ACTIVATE))
+				unlock_page(page);
 			if (ret || (--(wbc->nr_to_write) <= 0))
 				done = 1;
 			if (wbc->nonblocking && bdi_write_congested(bdi)) {
@@ -753,7 +746,6 @@
 	return ret;
 }
 EXPORT_SYMBOL(mpage_writepages);
-EXPORT_SYMBOL(__mpage_writepages);
 
 int mpage_writepage(struct page *page, get_block_t get_block,
 	struct writeback_control *wbc)
diff --git a/fs/namei.c b/fs/namei.c
index 9e4aef2..defe678 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -686,11 +686,11 @@
 
 /*
  * Name resolution.
+ * This is the basic name resolution function, turning a pathname into
+ * the final dentry. We expect 'base' to be positive and a directory.
  *
- * This is the basic name resolution function, turning a pathname
- * into the final dentry.
- *
- * We expect 'base' to be positive and a directory.
+ * Returns 0 and nd will have valid dentry and mnt on success.
+ * Returns error and drops reference to input namei data on failure.
  */
 static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
 {
@@ -929,8 +929,10 @@
 	return link_path_walk(name, nd);
 }
 
-/* SMP-safe */
-/* returns 1 if everything is done */
+/* 
+ * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if
+ * everything is done. Returns 0 and drops input nd, if lookup failed;
+ */
 static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
 {
 	if (path_walk(name, nd))
@@ -994,9 +996,10 @@
 	}
 }
 
+/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
 int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
 {
-	int retval;
+	int retval = 0;
 
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
@@ -1009,7 +1012,7 @@
 			nd->dentry = dget(current->fs->altroot);
 			read_unlock(&current->fs->lock);
 			if (__emul_lookup_dentry(name,nd))
-				return 0;
+				goto out; /* found in altroot */
 			read_lock(&current->fs->lock);
 		}
 		nd->mnt = mntget(current->fs->rootmnt);
@@ -1021,6 +1024,7 @@
 	read_unlock(&current->fs->lock);
 	current->total_link_count = 0;
 	retval = link_path_walk(name, nd);
+out:
 	if (unlikely(current->audit_context
 		     && nd && nd->dentry && nd->dentry->d_inode))
 		audit_inode(name, nd->dentry->d_inode);
@@ -2067,8 +2071,8 @@
  *	   ->i_sem on parents, which works but leads to some truely excessive
  *	   locking].
  */
-int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-	       struct inode *new_dir, struct dentry *new_dentry)
+static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
+			  struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error = 0;
 	struct inode *target;
@@ -2112,8 +2116,8 @@
 	return error;
 }
 
-int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-	       struct inode *new_dir, struct dentry *new_dentry)
+static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
+			    struct inode *new_dir, struct dentry *new_dentry)
 {
 	struct inode *target;
 	int error;
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index b74c4e3..87f4f9a 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -79,7 +79,7 @@
 		     char __user *, size_t);
 static ssize_t   idmap_pipe_downcall(struct file *, const char __user *,
 		     size_t);
-void             idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
+static void      idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
 
 static unsigned int fnvhash32(const void *, size_t);
 
@@ -434,7 +434,7 @@
 	return ret;
 }
 
-void
+static void
 idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
 {
 	struct idmap_msg *im = msg->data;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6345f26..f2317f3 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1904,7 +1904,7 @@
 	}
 }
  
-int nfs_init_inodecache(void)
+static int nfs_init_inodecache(void)
 {
 	nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
 					     sizeof(struct nfs_inode),
@@ -1916,7 +1916,7 @@
 	return 0;
 }
 
-void nfs_destroy_inodecache(void)
+static void nfs_destroy_inodecache(void)
 {
 	if (kmem_cache_destroy(nfs_inode_cachep))
 		printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index 8975127..a912deb 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -243,7 +243,7 @@
 	module_put(nls->owner);
 }
 
-wchar_t charset2uni[256] = {
+static wchar_t charset2uni[256] = {
 	/* 0x00*/
 	0x0000, 0x0001, 0x0002, 0x0003,
 	0x0004, 0x0005, 0x0006, 0x0007,
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 17ee1b4..584a27b 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -114,9 +114,6 @@
 		 */
 		for (i=0; i<4; i++, p++) {
 			u32 offs, size, next;
-
-			if (SYS_IND(p) == 0)
-				continue;
 			if (!NR_SECTS(p) || is_extended_partition(p))
 				continue;
 
@@ -433,8 +430,6 @@
 	for (slot = 1 ; slot <= 4 ; slot++, p++) {
 		u32 start = START_SECT(p)*sector_size;
 		u32 size = NR_SECTS(p)*sector_size;
-		if (SYS_IND(p) == 0)
-			continue;
 		if (!size)
 			continue;
 		if (is_extended_partition(p)) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 39fd336..e31903a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -820,7 +820,7 @@
 		goto out_free_page;
 
 	}
-	length = audit_set_loginuid(task->audit_context, loginuid);
+	length = audit_set_loginuid(task, loginuid);
 	if (likely(length == 0))
 		length = count;
 
@@ -1419,6 +1419,8 @@
 static struct inode_operations proc_tgid_attr_inode_operations;
 #endif
 
+static int get_tid_list(int index, unsigned int *tids, struct inode *dir);
+
 /* SMP-safe */
 static struct dentry *proc_pident_lookup(struct inode *dir, 
 					 struct dentry *dentry,
@@ -1458,7 +1460,7 @@
 	 */
 	switch(p->type) {
 		case PROC_TGID_TASK:
-			inode->i_nlink = 3;
+			inode->i_nlink = 2 + get_tid_list(2, NULL, dir);
 			inode->i_op = &proc_task_inode_operations;
 			inode->i_fop = &proc_task_operations;
 			break;
@@ -1701,13 +1703,13 @@
 };
 
 /**
- * proc_pid_unhash -  Unhash /proc/<pid> entry from the dcache.
+ * proc_pid_unhash -  Unhash /proc/@pid entry from the dcache.
  * @p: task that should be flushed.
  *
- * Drops the /proc/<pid> dcache entry from the hash chains.
+ * Drops the /proc/@pid dcache entry from the hash chains.
  *
- * Dropping /proc/<pid> entries and detach_pid must be synchroneous,
- * otherwise e.g. /proc/<pid>/exe might point to the wrong executable,
+ * Dropping /proc/@pid entries and detach_pid must be synchroneous,
+ * otherwise e.g. /proc/@pid/exe might point to the wrong executable,
  * if the pid value is immediately reused. This is enforced by
  * - caller must acquire spin_lock(p->proc_lock)
  * - must be called before detach_pid()
@@ -1739,8 +1741,8 @@
 }
 
 /**
- * proc_pid_flush - recover memory used by stale /proc/<pid>/x entries
- * @proc_entry: directoy to prune.
+ * proc_pid_flush - recover memory used by stale /proc/@pid/x entries
+ * @proc_dentry: directoy to prune.
  *
  * Shrink the /proc directory that was used by the just killed thread.
  */
@@ -1800,8 +1802,12 @@
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tgid_base_inode_operations;
 	inode->i_fop = &proc_tgid_base_operations;
-	inode->i_nlink = 3;
 	inode->i_flags|=S_IMMUTABLE;
+#ifdef CONFIG_SECURITY
+	inode->i_nlink = 5;
+#else
+	inode->i_nlink = 4;
+#endif
 
 	dentry->d_op = &pid_base_dentry_operations;
 
@@ -1855,8 +1861,12 @@
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tid_base_inode_operations;
 	inode->i_fop = &proc_tid_base_operations;
-	inode->i_nlink = 3;
 	inode->i_flags|=S_IMMUTABLE;
+#ifdef CONFIG_SECURITY
+	inode->i_nlink = 4;
+#else
+	inode->i_nlink = 3;
+#endif
 
 	dentry->d_op = &pid_base_dentry_operations;
 
@@ -1935,7 +1945,8 @@
 
 		if (--index >= 0)
 			continue;
-		tids[nr_tids] = tid;
+		if (tids != NULL)
+			tids[nr_tids] = tid;
 		nr_tids++;
 		if (nr_tids >= PROC_MAXPIDS)
 			break;
@@ -2035,6 +2046,7 @@
 	}
 
 	nr_tids = get_tid_list(pos, tid_array, inode);
+	inode->i_nlink = pos + nr_tids;
 
 	for (i = 0; i < nr_tids; i++) {
 		unsigned long j = PROC_NUMBUF;
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index a4e2ed5..49c479c 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -260,8 +260,9 @@
 /*
  * the packing is returned in disk byte order
  */
-u32 reiserfs_choose_packing(struct inode *dir) {
-    u32 packing;
+__le32 reiserfs_choose_packing(struct inode *dir)
+{
+    __le32 packing;
     if (TEST_OPTION(packing_groups, dir->i_sb)) {
 	u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id);
 	/*
@@ -655,7 +656,7 @@
     struct buffer_head * bh;
     struct item_head * ih;
     int pos_in_item;
-    __u32 * item;
+    __le32 * item;
     int ret = 0;
 
     if (!hint->path)		/* reiserfs code can call this function w/o pointer to path
@@ -736,7 +737,7 @@
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
 static inline void displace_new_packing_locality (reiserfs_blocknr_hint_t *hint)
 {
-    struct reiserfs_key * key = &hint->key;
+    struct in_core_key * key = &hint->key;
 
     hint->th->displace_new_blocks = 0;
     hint->search_start = hint->beg + keyed_hash((char*)(&key->k_objectid),4) % (hint->end - hint->beg);
@@ -777,7 +778,7 @@
 
 static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint)
 {
-    struct reiserfs_key * key = &hint->key;
+    struct in_core_key * key = &hint->key;
     b_blocknr_t slice_start;
 
     slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100);
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index d1514a9..fbde4b0 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -209,8 +209,8 @@
 /* compose directory item containing "." and ".." entries (entries are
    not aligned to 4 byte boundary) */
 /* the last four params are LE */
-void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid,
-			     __u32 par_dirid, __u32 par_objid)
+void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid,
+			     __le32 par_dirid, __le32 par_objid)
 {
     struct reiserfs_de_head * deh;
 
@@ -242,8 +242,8 @@
 }
 
 /* compose directory item containing "." and ".." entries */
-void make_empty_dir_item (char * body, __u32 dirid, __u32 objid,
-			  __u32 par_dirid, __u32 par_objid)
+void make_empty_dir_item (char * body, __le32 dirid, __le32 objid,
+			  __le32 par_dirid, __le32 par_objid)
 {
     struct reiserfs_de_head * deh;
 
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 2695011..2230aff 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -166,7 +166,7 @@
     struct cpu_key key; // cpu key of item that we are going to deal with
     struct item_head *ih; // pointer to item head that we are going to deal with
     struct buffer_head *bh; // Buffer head that contains items that we are going to deal with
-    __u32 * item; // pointer to item we are going to deal with
+    __le32 * item; // pointer to item we are going to deal with
     INITIALIZE_PATH(path); // path to item, that we are going to deal with.
     b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored.
     reiserfs_blocknr_hint_t hint; // hint structure for block allocator.
@@ -891,7 +891,7 @@
     struct item_head *ih = NULL; // pointer to item head that we are going to deal with
     struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with
     INITIALIZE_PATH(path); // path to item, that we are going to deal with.
-    __u32 * item=NULL; // pointer to item we are going to deal with
+    __le32 * item=NULL; // pointer to item we are going to deal with
     int item_pos=-1; /* Position in indirect item */
 
 
@@ -1284,10 +1284,11 @@
 	reiserfs_claim_blocks_to_be_allocated(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
 	reiserfs_write_unlock(inode->i_sb);
 
-	if ( !num_pages ) { /* If we do not have enough space even for */
-	    res = -ENOSPC;  /* single page, return -ENOSPC */
-	    if ( pos > (inode->i_size & (inode->i_sb->s_blocksize-1)))
-		break; // In case we are writing past the file end, break.
+	if ( !num_pages ) { /* If we do not have enough space even for a single page... */
+	    if ( pos > inode->i_size+inode->i_sb->s_blocksize-(pos & (inode->i_sb->s_blocksize-1))) {
+		res = -ENOSPC;
+		break; // In case we are writing past the end of the last file block, break.
+	    }
 	    // Otherwise we are possibly overwriting the file, so
 	    // let's set write size to be equal or less than blocksize.
 	    // This way we get it correctly for file holes.
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 7543031..2711dff 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -173,7 +173,7 @@
    done already or non-hole position has been found in the indirect item */
 static inline int allocation_needed (int retval, b_blocknr_t allocated, 
 				     struct item_head * ih,
-				     __u32 * item, int pos_in_item)
+				     __le32 * item, int pos_in_item)
 {
   if (allocated)
 	 return 0;
@@ -278,7 +278,7 @@
     bh = get_last_bh (&path);
     ih = get_ih (&path);
     if (is_indirect_le_ih (ih)) {
-	__u32 * ind_item = (__u32 *)B_I_PITEM (bh, ih);
+	__le32 * ind_item = (__le32 *)B_I_PITEM (bh, ih);
 	
 	/* FIXME: here we could cache indirect item or part of it in
 	   the inode to avoid search_by_key in case of subsequent
@@ -581,7 +581,7 @@
     struct cpu_key key;
     struct buffer_head * bh, * unbh = NULL;
     struct item_head * ih, tmp_ih;
-    __u32 * item;
+    __le32 * item;
     int done;
     int fs_gen;
     struct reiserfs_transaction_handle *th = NULL;
@@ -746,7 +746,7 @@
     done = 0;
     do {
 	if (is_statdata_le_ih (ih)) {
-	    __u32 unp = 0;
+	    __le32 unp = 0;
 	    struct cpu_key tmp_key;
 
 	    /* indirect item has to be inserted */
@@ -1341,8 +1341,8 @@
     key.version = KEY_FORMAT_3_5;
     key.on_disk_key.k_dir_id = dirino;
     key.on_disk_key.k_objectid = inode->i_ino;
-    key.on_disk_key.u.k_offset_v1.k_offset = SD_OFFSET;
-    key.on_disk_key.u.k_offset_v1.k_uniqueness = SD_UNIQUENESS;
+    key.on_disk_key.k_offset = 0;
+    key.on_disk_key.k_type = 0;
 
     /* look for the object's stat data */
     retval = search_item (inode->i_sb, &key, &path_to_sd);
@@ -2067,7 +2067,7 @@
     struct item_head tmp_ih ;
     struct item_head *ih ;
     struct buffer_head *bh ;
-    __u32 *item ;
+    __le32 *item ;
     struct cpu_key key ;
     INITIALIZE_PATH(path) ;
     int pos_in_item ;
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
index 9cf7c13..0ce33db 100644
--- a/fs/reiserfs/item_ops.c
+++ b/fs/reiserfs/item_ops.c
@@ -296,10 +296,11 @@
 static void indirect_print_item (struct item_head * ih, char * item)
 {
     int j;
-    __u32 * unp, prev = INT_MAX;
+    __le32 * unp;
+    __u32 prev = INT_MAX;
     int num;
 
-    unp = (__u32 *)item;
+    unp = (__le32 *)item;
 
     if (ih_item_len(ih) % UNFM_P_SIZE)
 	reiserfs_warning (NULL, "indirect_print_item: invalid item len");
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index c9ad3a7..3072cfd 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2306,13 +2306,16 @@
 	if( !IS_ERR( journal -> j_dev_file ) ) {
 		struct inode *jdev_inode = journal->j_dev_file->f_mapping->host;
 		if( !S_ISBLK( jdev_inode -> i_mode ) ) {
-			reiserfs_warning  (super, "journal_init_dev: '%s' is "
-					   "not a block device", jdev_name );
+			reiserfs_warning(super, "journal_init_dev: '%s' is "
+					 "not a block device", jdev_name );
 			result = -ENOTBLK;
+			release_journal_dev( super, journal );
 		} else  {
 			/* ok */
 			journal->j_dev_bd = I_BDEV(jdev_inode);
 			set_blocksize(journal->j_dev_bd, super->s_blocksize);
+			reiserfs_info(super, "journal_init_dev: journal device: %s\n",
+				      bdevname(journal->j_dev_bd, b));
 		}
 	} else {
 		result = PTR_ERR( journal -> j_dev_file );
@@ -2321,11 +2324,6 @@
 				  "journal_init_dev: Cannot open '%s': %i",
 				  jdev_name, result );
 	}
-	if( result != 0 ) {
-		release_journal_dev( super, journal );
-	}
-	reiserfs_info(super, "journal_init_dev: journal device: %s\n",
-		bdevname(journal->j_dev_bd, b));
 	return result;
 }
 
@@ -2393,7 +2391,7 @@
      jh = (struct reiserfs_journal_header *)(bhjh->b_data);
      
      /* make sure that journal matches to the super block */
-     if (is_reiserfs_jr(rs) && (jh->jh_journal.jp_journal_magic != sb_jp_journal_magic(rs))) {
+     if (is_reiserfs_jr(rs) && (le32_to_cpu(jh->jh_journal.jp_journal_magic) != sb_jp_journal_magic(rs))) {
 	 reiserfs_warning (p_s_sb, "sh-460: journal header magic %x "
 			   "(device %s) does not match to magic found in super "
 			   "block %x",
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 80e92d9..7d4dc5f 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -608,7 +608,7 @@
         goto out_failed;
     }
 
-    retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode);
+    retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode);
     if (retval)
         goto out_failed;
 	
diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c
index 0785c43..bfe8e25 100644
--- a/fs/reiserfs/objectid.c
+++ b/fs/reiserfs/objectid.c
@@ -11,13 +11,13 @@
 
 // find where objectid map starts
 #define objectid_map(s,rs) (old_format_only (s) ? \
-                         (__u32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\
-			 (__u32 *)((rs) + 1))
+                         (__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\
+			 (__le32 *)((rs) + 1))
 
 
 #ifdef CONFIG_REISERFS_CHECK
 
-static void check_objectid_map (struct super_block * s, __u32 * map)
+static void check_objectid_map (struct super_block * s, __le32 * map)
 {
     if (le32_to_cpu (map[0]) != 1)
 	reiserfs_panic (s, "vs-15010: check_objectid_map: map corrupted: %lx",
@@ -27,7 +27,7 @@
 }
 
 #else
-static void check_objectid_map (struct super_block * s, __u32 * map)
+static void check_objectid_map (struct super_block * s, __le32 * map)
 {;}
 #endif
 
@@ -52,7 +52,7 @@
 {
     struct super_block * s = th->t_super;
     struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s);
-    __u32 * map = objectid_map (s, rs);
+    __le32 * map = objectid_map (s, rs);
     __u32 unused_objectid;
 
     BUG_ON (!th->t_trans_id);
@@ -97,7 +97,7 @@
 {
     struct super_block * s = th->t_super;
     struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s);
-    __u32 * map = objectid_map (s, rs);
+    __le32 * map = objectid_map (s, rs);
     int i = 0;
 
     BUG_ON (!th->t_trans_id);
@@ -172,12 +172,12 @@
     int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2 ;
     int old_max = sb_oid_maxsize(disk_sb);
     struct reiserfs_super_block_v1 *disk_sb_v1 ;
-    __u32 *objectid_map, *new_objectid_map ;
+    __le32 *objectid_map, *new_objectid_map ;
     int i ;
 
     disk_sb_v1=(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data);
-    objectid_map = (__u32 *)(disk_sb_v1 + 1) ;
-    new_objectid_map = (__u32 *)(disk_sb + 1) ;
+    objectid_map = (__le32 *)(disk_sb_v1 + 1) ;
+    new_objectid_map = (__le32 *)(disk_sb + 1) ;
 
     if (cur_size > new_size) {
 	/* mark everyone used that was listed as free at the end of the objectid
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index f4ea81a..e242ebc 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -73,8 +73,8 @@
 #define DFL( x ) D4C( rs -> s_v1.x )
 
 #define objectid_map( s, rs ) (old_format_only (s) ?				\
-                         (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1) :	\
-			 (__u32 *)(rs + 1))
+                         (__le32 *)((struct reiserfs_super_block_v1 *)rs + 1) :	\
+			 (__le32 *)(rs + 1))
 #define MAP( i ) D4C( objectid_map( sb, rs )[ i ] )
 
 #define DJF( x ) le32_to_cpu( rs -> x )
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 73ec521..da23ba7 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -87,22 +87,20 @@
 inline int  comp_short_keys (const struct reiserfs_key * le_key,
 			     const struct cpu_key * cpu_key)
 {
-  __u32 * p_s_le_u32, * p_s_cpu_u32;
-  int n_key_length = REISERFS_SHORT_KEY_LEN;
-
-  p_s_le_u32 = (__u32 *)le_key;
-  p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key;
-  for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) {
-    if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 )
+  __u32 n;
+  n = le32_to_cpu(le_key->k_dir_id);
+  if (n < cpu_key->on_disk_key.k_dir_id)
       return -1;
-    if ( le32_to_cpu (*p_s_le_u32) > *p_s_cpu_u32 )
+  if (n > cpu_key->on_disk_key.k_dir_id)
       return 1;
-  }
-
+  n = le32_to_cpu(le_key->k_objectid);
+  if (n < cpu_key->on_disk_key.k_objectid)
+      return -1;
+  if (n > cpu_key->on_disk_key.k_objectid)
+      return 1;
   return 0;
 }
 
-
 /* k1 is pointer to on-disk structure which is stored in little-endian
    form. k2 is pointer to cpu variable.
    Compare keys using all 4 key fields.
@@ -152,18 +150,15 @@
 
 inline void le_key2cpu_key (struct cpu_key * to, const struct reiserfs_key * from)
 {
+    int version;
     to->on_disk_key.k_dir_id = le32_to_cpu (from->k_dir_id);
     to->on_disk_key.k_objectid = le32_to_cpu (from->k_objectid);
     
     // find out version of the key
-    to->version = le_key_version (from);
-    if (to->version == KEY_FORMAT_3_5) {
-	to->on_disk_key.u.k_offset_v1.k_offset = le32_to_cpu (from->u.k_offset_v1.k_offset);
-	to->on_disk_key.u.k_offset_v1.k_uniqueness = le32_to_cpu (from->u.k_offset_v1.k_uniqueness);
-    } else {
-	to->on_disk_key.u.k_offset_v2.k_offset = offset_v2_k_offset(&from->u.k_offset_v2);
-	to->on_disk_key.u.k_offset_v2.k_type = offset_v2_k_type(&from->u.k_offset_v2);
-    } 
+    version = le_key_version (from);
+    to->version = version;
+    to->on_disk_key.k_offset = le_key_k_offset(version, from);
+    to->on_disk_key.k_type = le_key_k_type(version, from);
 }
 
 
@@ -228,8 +223,14 @@
 const struct reiserfs_key  MIN_KEY = {0, 0, {{0, 0},}};
 
 /* Maximal possible key. It is never in the tree. */
-const struct reiserfs_key  MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}};
+const struct reiserfs_key  MAX_KEY = {
+	__constant_cpu_to_le32(0xffffffff),
+	__constant_cpu_to_le32(0xffffffff),
+	{{__constant_cpu_to_le32(0xffffffff),
+	__constant_cpu_to_le32(0xffffffff)},}
+};
 
+const struct in_core_key  MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15};
 
 /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
    of the path, and going upwards.  We must check the path's validity at each step.  If the key is not in
@@ -997,7 +998,7 @@
 	int                   n_unfm_number,    /* Number of the item unformatted nodes. */
 	    n_counter,
 	    n_blk_size;
-	__u32               * p_n_unfm_pointer; /* Pointer to the unformatted node number. */
+	__le32               * p_n_unfm_pointer; /* Pointer to the unformatted node number. */
 	__u32 tmp;
 	struct item_head      s_ih;           /* Item header. */
 	char                  c_mode;           /* Returned mode of the balance. */
@@ -1059,7 +1060,7 @@
 	    /* pointers to be cut */
 	    n_unfm_number -= pos_in_item (p_s_path);
 	    /* Set pointer to the last unformatted node pointer that is to be cut. */
-	    p_n_unfm_pointer = (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed;
+	    p_n_unfm_pointer = (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed;
 
 
 	    /* We go through the unformatted nodes pointers of the indirect
@@ -1081,8 +1082,8 @@
 		    need_research = 1 ;
 		    break;
 		}
-		RFALSE( p_n_unfm_pointer < (__u32 *)B_I_PITEM(p_s_bh, &s_ih) ||
-			p_n_unfm_pointer > (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1,
+		RFALSE( p_n_unfm_pointer < (__le32 *)B_I_PITEM(p_s_bh, &s_ih) ||
+			p_n_unfm_pointer > (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1,
 			"vs-5265: pointer out of range");
 
 		/* Hole, nothing to remove. */
@@ -1431,7 +1432,7 @@
 #if defined( USE_INODE_GENERATION_COUNTER )
     if( !old_format_only ( th -> t_super ) )
       {
-       __u32 *inode_generation;
+       __le32 *inode_generation;
        
        inode_generation = 
          &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index bcdf243..31e7512 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -110,7 +110,7 @@
   reiserfs_allow_writes(s) ;
 }
 
-extern const struct reiserfs_key  MAX_KEY;
+extern const struct in_core_key  MAX_IN_CORE_KEY;
 
 
 /* this is used to delete "save link" when there are no items of a
@@ -164,7 +164,7 @@
  
     /* compose key to look for "save" links */
     max_cpu_key.version = KEY_FORMAT_3_5;
-    max_cpu_key.on_disk_key = MAX_KEY;
+    max_cpu_key.on_disk_key = MAX_IN_CORE_KEY;
     max_cpu_key.key_length = 3;
 
 #ifdef CONFIG_QUOTA
@@ -216,10 +216,10 @@
  
         /* reiserfs_iget needs k_dirid and k_objectid only */
         item = B_I_PITEM (bh, ih);
-        obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item);
+        obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__le32 *)item);
         obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid);
-	obj_key.on_disk_key.u.k_offset_v1.k_offset = 0;
-	obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0;
+	obj_key.on_disk_key.k_offset = 0;
+	obj_key.on_disk_key.k_type = 0;
 	
         pathrelse (&path);
  
@@ -304,7 +304,7 @@
     int retval;
     struct cpu_key key;
     struct item_head ih;
-    __u32 link;
+    __le32 link;
 
     BUG_ON (!th->t_trans_id);
 
@@ -889,12 +889,18 @@
 	    char * p;
 	    
 	    p = NULL;
-	    /* "resize=NNN" */
-	    *blocks = simple_strtoul (arg, &p, 0);
-	    if (*p != '\0') {
-		/* NNN does not look like a number */
-		reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg);
-		return 0;
+	    /* "resize=NNN" or "resize=auto" */
+
+	    if (!strcmp(arg, "auto")) {
+		    /* From JFS code, to auto-get the size.*/
+		    *blocks = s->s_bdev->bd_inode->i_size >> s->s_blocksize_bits;
+	    } else {
+		    *blocks = simple_strtoul (arg, &p, 0);
+		    if (*p != '\0') {
+			/* NNN does not look like a number */
+			reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg);
+			return 0;
+		    }
 	    }
 	}
 
@@ -903,7 +909,8 @@
 		unsigned long val = simple_strtoul (arg, &p, 0);
 		/* commit=NNN (time in seconds) */
 		if ( *p != '\0' || val >= (unsigned int)-1) {
-			reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg);			return 0;
+			reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg);
+			return 0;
 		}
 		*commit_max_age = (unsigned int)val;
 	}
@@ -1329,7 +1336,7 @@
 	return 1;
     }
 
-    if ( rs->s_v1.s_root_block == -1 ) {
+    if ( rs->s_v1.s_root_block == cpu_to_le32(-1) ) {
        brelse(bh) ;
        reiserfs_warning (s, "Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
               "reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
diff --git a/fs/select.c b/fs/select.c
index 25b1cca..b80e7eb 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -55,7 +55,8 @@
  * as all select/poll functions have to call it to add an entry to the
  * poll table.
  */
-void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p);
+static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
+		       poll_table *p);
 
 void poll_initwait(struct poll_wqueues *pwq)
 {
@@ -87,7 +88,8 @@
 
 EXPORT_SYMBOL(poll_freewait);
 
-void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p)
+static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
+		       poll_table *_p)
 {
 	struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt);
 	struct poll_table_page *table = p->table;
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 650c43b..38ef913 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -51,7 +51,10 @@
 
 /**
  *	seq_read -	->read() method for sequential files.
- *	@file, @buf, @size, @ppos: see file_operations method
+ *	@file: the file to read from
+ *	@buf: the buffer to read to
+ *	@size: the maximum number of bytes to read
+ *	@ppos: the current position in the file
  *
  *	Ready-made ->f_op->read()
  */
@@ -219,7 +222,9 @@
 
 /**
  *	seq_lseek -	->llseek() method for sequential files.
- *	@file, @offset, @origin: see file_operations method
+ *	@file: the file in question
+ *	@offset: new position
+ *	@origin: 0 for absolute, 1 for relative position
  *
  *	Ready-made ->f_op->llseek()
  */
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index da25aeb..3642080 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -96,7 +96,7 @@
 /**
  *	flush_read_buffer - push buffer to userspace.
  *	@buffer:	data buffer for file.
- *	@userbuf:	user-passed buffer.
+ *	@buf:		user-passed buffer.
  *	@count:		number of bytes requested.
  *	@ppos:		file position.
  *
@@ -164,7 +164,7 @@
 /**
  *	fill_write_buffer - copy buffer from userspace.
  *	@buffer:	data buffer for file.
- *	@userbuf:	data from user.
+ *	@buf:		data from user.
  *	@count:		number of bytes in @userbuf.
  *
  *	Allocate @buffer->page if it hasn't been already, then
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 2faa417..bb40d63 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -49,8 +49,7 @@
 	struct inode *inode = page->mapping->host;
 	char *kaddr;
 
-	if (!PageLocked(page))
-		PAGE_BUG(page);
+	BUG_ON(!PageLocked(page));
 
 	kaddr = kmap(page);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
@@ -67,8 +66,7 @@
 	struct inode *inode = page->mapping->host;
 	char *kaddr;
 
-	if (!PageLocked(page))
-		PAGE_BUG(page);
+	BUG_ON(!PageLocked(page));
 
 	kaddr = kmap(page);
 	memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 0506e11..3d68de3 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -167,8 +167,8 @@
 	}
 
 	page = grab_cache_page(inode->i_mapping, 0);
-	if (!PageLocked(page))
-		PAGE_BUG(page);
+	BUG_ON(!PageLocked(page));
+
 	if (!PageUptodate(page))
 	{
 		kaddr = kmap(page);
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index c2634bd..457a8fe 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -103,7 +103,7 @@
 		offset = 0;
 
 	if ((src.year < EPOCH_YEAR) ||
-		(src.year > EPOCH_YEAR+MAX_YEAR_SECONDS))
+		(src.year >= EPOCH_YEAR+MAX_YEAR_SECONDS))
 	{
 		*dest = -1;
 		*dest_usec = -1;
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 554e4a1..d3ff783 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -49,7 +49,7 @@
 	EXTRA_CFLAGS += -DXFS_LOG_TRACE
 	EXTRA_CFLAGS += -DXFS_RW_TRACE
 	EXTRA_CFLAGS += -DPAGEBUF_TRACE
-	# EXTRA_CFLAGS += -DXFS_VNODE_TRACE
+	EXTRA_CFLAGS += -DXFS_VNODE_TRACE
 endif
 
 obj-$(CONFIG_XFS_FS)		+= xfs.o
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 76a8475..9278e9ab 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -558,7 +558,8 @@
 	int			i;
 
 	BUG_ON(PageWriteback(page));
-	set_page_writeback(page);
+	if (bh_count)
+		set_page_writeback(page);
 	if (clear_dirty)
 		clear_page_dirty(page);
 	unlock_page(page);
@@ -578,9 +579,6 @@
 
 		if (probed_page && clear_dirty)
 			wbc->nr_to_write--;	/* Wrote an "extra" page */
-	} else {
-		end_page_writeback(page);
-		wbc->pages_skipped++;	/* We didn't write this page */
 	}
 }
 
@@ -602,21 +600,26 @@
 {
 	struct buffer_head	*bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
 	xfs_iomap_t		*mp = iomapp, *tmp;
-	unsigned long		end, offset;
-	pgoff_t			end_index;
-	int			i = 0, index = 0;
+	unsigned long		offset, end_offset;
+	int			index = 0;
 	int			bbits = inode->i_blkbits;
+	int			len, page_dirty;
 
-	end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
-	if (page->index < end_index) {
-		end = PAGE_CACHE_SIZE;
-	} else {
-		end = i_size_read(inode) & (PAGE_CACHE_SIZE-1);
-	}
+	end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1));
+
+	/*
+	 * page_dirty is initially a count of buffers on the page before
+	 * EOF and is decrememted as we move each into a cleanable state.
+	 */
+	len = 1 << inode->i_blkbits;
+	end_offset = max(end_offset, PAGE_CACHE_SIZE);
+	end_offset = roundup(end_offset, len);
+	page_dirty = end_offset / len;
+
+	offset = 0;
 	bh = head = page_buffers(page);
 	do {
-		offset = i << bbits;
-		if (offset >= end)
+		if (offset >= end_offset)
 			break;
 		if (!(PageUptodate(page) || buffer_uptodate(bh)))
 			continue;
@@ -625,6 +628,7 @@
 			if (startio) {
 				lock_buffer(bh);
 				bh_arr[index++] = bh;
+				page_dirty--;
 			}
 			continue;
 		}
@@ -657,10 +661,11 @@
 			unlock_buffer(bh);
 			mark_buffer_dirty(bh);
 		}
-	} while (i++, (bh = bh->b_this_page) != head);
+		page_dirty--;
+	} while (offset += len, (bh = bh->b_this_page) != head);
 
-	if (startio) {
-		xfs_submit_page(page, wbc, bh_arr, index, 1, index == i);
+	if (startio && index) {
+		xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty);
 	} else {
 		unlock_page(page);
 	}
@@ -725,8 +730,11 @@
 	__uint64_t              end_offset;
 	pgoff_t                 end_index, last_index, tlast;
 	int			len, err, i, cnt = 0, uptodate = 1;
-	int			flags = startio ? 0 : BMAPI_TRYLOCK;
-	int			page_dirty, delalloc = 0;
+	int			flags;
+	int			page_dirty;
+
+	/* wait for other IO threads? */
+	flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK;
 
 	/* Is this page beyond the end of the file? */
 	offset = i_size_read(inode);
@@ -740,19 +748,22 @@
 		}
 	}
 
-	offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
 	end_offset = min_t(unsigned long long,
-			offset + PAGE_CACHE_SIZE, i_size_read(inode));
-
-	bh = head = page_buffers(page);
-	iomp = NULL;
+			(loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset);
+	offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
 
 	/*
-	 * page_dirty is initially a count of buffers on the page and
-	 * is decrememted as we move each into a cleanable state.
+	 * page_dirty is initially a count of buffers on the page before
+	 * EOF and is decrememted as we move each into a cleanable state.
 	 */
-	len = bh->b_size;
-	page_dirty = PAGE_CACHE_SIZE / len;
+	len = 1 << inode->i_blkbits;
+	p_offset = max(p_offset, PAGE_CACHE_SIZE);
+	p_offset = roundup(p_offset, len);
+	page_dirty = p_offset / len;
+
+	iomp = NULL;
+	p_offset = 0;
+	bh = head = page_buffers(page);
 
 	do {
 		if (offset >= end_offset)
@@ -804,7 +815,6 @@
 		 */
 		} else if (buffer_delay(bh)) {
 			if (!iomp) {
-				delalloc = 1;
 				err = xfs_map_blocks(inode, offset, len, &iomap,
 						BMAPI_ALLOCATE | flags);
 				if (err) {
@@ -875,14 +885,15 @@
 	if (uptodate && bh == head)
 		SetPageUptodate(page);
 
-	if (startio)
-		xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1);
+	if (startio) {
+		WARN_ON(page_dirty);
+		xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty);
+	}
 
 	if (iomp) {
-		tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
+		offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
 					PAGE_CACHE_SHIFT;
-		if (delalloc && (tlast > last_index))
-			tlast = last_index;
+		tlast = min_t(pgoff_t, offset, last_index);
 		xfs_cluster_write(inode, page->index + 1, iomp, wbc,
 					startio, unmapped, tlast);
 	}
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 23e0eb6..997963e 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1746,13 +1746,15 @@
 STATIC struct task_struct *pagebuf_daemon_task;
 STATIC int pagebuf_daemon_active;
 STATIC int force_flush;
-
+STATIC int force_sleep;
 
 STATIC int
 pagebuf_daemon_wakeup(
 	int			priority,
 	unsigned int		mask)
 {
+	if (force_sleep)
+		return 0;
 	force_flush = 1;
 	barrier();
 	wake_up_process(pagebuf_daemon_task);
@@ -1778,7 +1780,12 @@
 
 	INIT_LIST_HEAD(&tmp);
 	do {
-		try_to_freeze(PF_FREEZE);
+		if (unlikely(current->flags & PF_FREEZE)) {
+			force_sleep = 1;
+			refrigerator(PF_FREEZE);
+		} else {
+			force_sleep = 0;
+		}
 
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 9f057a4..d0d412a 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -515,10 +515,49 @@
 }
 #endif /* HAVE_FOP_OPEN_EXEC */
 
+/*
+ * Temporary workaround to the AIO direct IO write problem.
+ * This code can go and we can revert to do_sync_write once
+ * the writepage(s) rework is merged.
+ */
+STATIC ssize_t
+linvfs_write(
+	struct file	*filp,
+	const char	__user *buf,
+	size_t		len,
+	loff_t		*ppos)
+{
+	struct kiocb	kiocb;
+	ssize_t		ret;
+
+	init_sync_kiocb(&kiocb, filp);
+	kiocb.ki_pos = *ppos;
+	ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos);
+	*ppos = kiocb.ki_pos;
+	return ret;
+}
+STATIC ssize_t
+linvfs_write_invis(
+	struct file	*filp,
+	const char	__user *buf,
+	size_t		len,
+	loff_t		*ppos)
+{
+	struct kiocb	kiocb;
+	ssize_t		ret;
+
+	init_sync_kiocb(&kiocb, filp);
+	kiocb.ki_pos = *ppos;
+	ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos);
+	*ppos = kiocb.ki_pos;
+	return ret;
+}
+
+
 struct file_operations linvfs_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
-	.write		= do_sync_write,
+	.write		= linvfs_write,
 	.readv		= linvfs_readv,
 	.writev		= linvfs_writev,
 	.aio_read	= linvfs_aio_read,
@@ -540,7 +579,7 @@
 struct file_operations linvfs_invis_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
-	.write		= do_sync_write,
+	.write		= linvfs_write_invis,
 	.readv		= linvfs_readv_invis,
 	.writev		= linvfs_writev_invis,
 	.aio_read	= linvfs_aio_read_invis,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ff145fd..aa9daae 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -683,6 +683,9 @@
 			(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
 
+		if (ioflags & IO_ISAIO)
+			return XFS_ERROR(-ENOSYS);
+
 		if ((pos & target->pbr_smask) || (count & target->pbr_smask))
 			return XFS_ERROR(-EINVAL);
 
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 849c61c..a832d16 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -156,7 +156,6 @@
 
 #ifdef	XFS_VNODE_TRACE
 	vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
-	printk("Allocated VNODE_TRACE at 0x%p\n", vp->v_trace);
 #endif	/* XFS_VNODE_TRACE */
 
 	vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
@@ -424,13 +423,13 @@
  * Vnode tracing code.
  */
 void
-vn_trace_entry(vnode_t *vp, char *func, inst_t *ra)
+vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
 }
 
 void
-vn_trace_exit(vnode_t *vp, char *func, inst_t *ra)
+vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
 }
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index da76c1f..00466c3 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -86,10 +86,11 @@
 	vnumber_t	v_number;		/* in-core vnode number */
 	vn_bhv_head_t	v_bh;			/* behavior head */
 	spinlock_t	v_lock;			/* VN_LOCK/VN_UNLOCK */
-	struct inode	v_inode;		/* Linux inode */
 #ifdef XFS_VNODE_TRACE
 	struct ktrace	*v_trace;		/* trace header structure    */
 #endif
+	struct inode	v_inode;		/* Linux inode */
+	/* inode MUST be last */
 } vnode_t;
 
 #define v_fbhv			v_bh.bh_first	       /* first behavior */
@@ -409,7 +410,7 @@
 	int		va_mask;	/* bit-mask of attributes present */
 	enum vtype	va_type;	/* vnode type (for create) */
 	mode_t		va_mode;	/* file access mode and type */
-	nlink_t		va_nlink;	/* number of references to file */
+	xfs_nlink_t	va_nlink;	/* number of references to file */
 	uid_t		va_uid;		/* owner user id */
 	gid_t		va_gid;		/* owner group id */
 	xfs_ino_t	va_nodeid;	/* file id */
@@ -625,6 +626,7 @@
 #define	ATTR_DMI	0x08	/* invocation from a DMI function */
 #define	ATTR_LAZY	0x80	/* set/get attributes lazily */
 #define	ATTR_NONBLOCK	0x100	/* return EAGAIN if operation would block */
+#define ATTR_NOLOCK	0x200	/* Don't grab any conflicting locks */
 
 /*
  * Flags to VOP_FSYNC and VOP_RECLAIM.
@@ -646,8 +648,8 @@
 #define	VNODE_KTRACE_REF	4
 #define	VNODE_KTRACE_RELE	5
 
-extern void vn_trace_entry(struct vnode *, char *, inst_t *);
-extern void vn_trace_exit(struct vnode *, char *, inst_t *);
+extern void vn_trace_entry(struct vnode *, const char *, inst_t *);
+extern void vn_trace_exit(struct vnode *, const char *, inst_t *);
 extern void vn_trace_hold(struct vnode *, char *, int, inst_t *);
 extern void vn_trace_ref(struct vnode *, char *, int, inst_t *);
 extern void vn_trace_rele(struct vnode *, char *, int, inst_t *);
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 08d551a..63abdc2 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -182,7 +182,7 @@
 
 	if (VN_CACHED(tvp) != 0)
 		xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore),
-						(loff_t)0, 0, 0);
+						(xfs_off_t)0, 0, 0);
 
 	/* Verify O_DIRECT for ftmp */
 	if (VN_CACHED(tvp) != 0) {
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3a0ba1d..d3da000 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -136,6 +136,40 @@
 }
 
 /*
+ * Try to move an inode to the front of its hash list if possible
+ * (and if its not there already).  Called right after obtaining
+ * the list version number and then dropping the read_lock on the
+ * hash list in question (which is done right after looking up the
+ * inode in question...).
+ */
+STATIC void
+xfs_ihash_promote(
+	xfs_ihash_t	*ih,
+	xfs_inode_t	*ip,
+	ulong		version)
+{
+	xfs_inode_t	*iq;
+
+	if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
+		if (likely(version == ih->ih_version)) {
+			/* remove from list */
+			if ((iq = ip->i_next)) {
+				iq->i_prevp = ip->i_prevp;
+			}
+			*ip->i_prevp = iq;
+
+			/* insert at list head */
+			iq = ih->ih_next;
+			iq->i_prevp = &ip->i_next;
+			ip->i_next = iq;
+			ip->i_prevp = &ih->ih_next;
+			ih->ih_next = ip;
+		}
+		write_unlock(&ih->ih_lock);
+	}
+}
+
+/*
  * Look up an inode by number in the given file system.
  * The inode is looked up in the hash table for the file system
  * represented by the mount point parameter mp.  Each bucket of
@@ -229,7 +263,9 @@
 				XFS_STATS_INC(xs_ig_found);
 
 				ip->i_flags &= ~XFS_IRECLAIMABLE;
+				version = ih->ih_version;
 				read_unlock(&ih->ih_lock);
+				xfs_ihash_promote(ih, ip, version);
 
 				XFS_MOUNT_ILOCK(mp);
 				list_del_init(&ip->i_reclaim);
@@ -259,8 +295,15 @@
 						inode_vp, vp);
 			}
 
+			/*
+			 * Inode cache hit: if ip is not at the front of
+			 * its hash chain, move it there now.
+			 * Do this with the lock held for update, but
+			 * do statistics after releasing the lock.
+			 */
+			version = ih->ih_version;
 			read_unlock(&ih->ih_lock);
-
+			xfs_ihash_promote(ih, ip, version);
 			XFS_STATS_INC(xs_ig_found);
 
 finish_inode:
@@ -547,6 +590,7 @@
 {
 	xfs_ihash_t	*ih;
 	xfs_inode_t	*ip;
+	ulong		version;
 
 	ih = XFS_IHASH(mp, ino);
 	read_lock(&ih->ih_lock);
@@ -554,11 +598,15 @@
 		if (ip->i_ino == ino) {
 			/*
 			 * If we find it and tp matches, return it.
+			 * Also move it to the front of the hash list
+			 * if we find it and it is not already there.
 			 * Otherwise break from the loop and return
 			 * NULL.
 			 */
 			if (ip->i_transp == tp) {
+				version = ih->ih_version;
 				read_unlock(&ih->ih_lock);
+				xfs_ihash_promote(ih, ip, version);
 				return (ip);
 			}
 			break;
@@ -685,6 +733,7 @@
 		iq->i_prevp = ip->i_prevp;
 	}
 	*ip->i_prevp = iq;
+	ih->ih_version++;
 	write_unlock(&ih->ih_lock);
 
 	/*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 43c632a..bc8c8c7 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1130,7 +1130,7 @@
 	xfs_trans_t	*tp,
 	xfs_inode_t	*pip,
 	mode_t		mode,
-	nlink_t		nlink,
+	xfs_nlink_t	nlink,
 	xfs_dev_t	rdev,
 	cred_t		*cr,
 	xfs_prid_t	prid,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index a53b1cc..37e1c31 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -495,9 +495,9 @@
 int		xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
 			  xfs_inode_t **, xfs_daddr_t);
 int		xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
-int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, nlink_t,
-			   xfs_dev_t, struct cred *, xfs_prid_t, int,
-			   struct xfs_buf **, boolean_t *, xfs_inode_t **);
+int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
+			   xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
+			   int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
 void		xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
 					int);
 uint		xfs_ip2xflags(struct xfs_inode *);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 3826e8f..991f8a6 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -308,7 +308,8 @@
 			break;
 		}
 
-		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps);
+		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count,
+						 &imap, &nimaps);
 		break;
 	case BMAPI_UNWRITTEN:
 		lockmode = 0;
@@ -365,7 +366,7 @@
 int
 xfs_iomap_write_direct(
 	xfs_inode_t	*ip,
-	loff_t		offset,
+	xfs_off_t	offset,
 	size_t		count,
 	int		flags,
 	xfs_bmbt_irec_t *ret_imap,
@@ -541,7 +542,7 @@
 int
 xfs_iomap_write_delay(
 	xfs_inode_t	*ip,
-	loff_t		offset,
+	xfs_off_t	offset,
 	size_t		count,
 	int		ioflag,
 	xfs_bmbt_irec_t *ret_imap,
@@ -746,6 +747,8 @@
 int
 xfs_iomap_write_allocate(
 	xfs_inode_t	*ip,
+	xfs_off_t	offset,
+	size_t		count,
 	xfs_bmbt_irec_t *map,
 	int		*retmap)
 {
@@ -770,9 +773,9 @@
 	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
 		return XFS_ERROR(error);
 
-	offset_fsb = map->br_startoff;
+	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 	count_fsb = map->br_blockcount;
-	map_start_fsb = offset_fsb;
+	map_start_fsb = map->br_startoff;
 
 	XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
 
@@ -868,9 +871,9 @@
 					imap[i].br_startoff,
 				        imap[i].br_blockcount,imap[i].br_state);
                         }
-			if ((map->br_startoff >= imap[i].br_startoff) &&
-			    (map->br_startoff < (imap[i].br_startoff +
-						 imap[i].br_blockcount))) {
+			if ((offset_fsb >= imap[i].br_startoff) &&
+			    (offset_fsb < (imap[i].br_startoff +
+					   imap[i].br_blockcount))) {
 				*map = imap[i];
 				*retmap = 1;
 				XFS_STATS_INC(xs_xstrat_quick);
@@ -883,9 +886,8 @@
 		 * file, just surrounding data, try again.
 		 */
 		nimaps--;
-		offset_fsb = imap[nimaps].br_startoff +
-			     imap[nimaps].br_blockcount;
-		map_start_fsb = offset_fsb;
+		map_start_fsb = imap[nimaps].br_startoff +
+				imap[nimaps].br_blockcount;
 	}
 
 trans_cancel:
@@ -899,7 +901,7 @@
 int
 xfs_iomap_write_unwritten(
 	xfs_inode_t	*ip,
-	loff_t		offset,
+	xfs_off_t	offset,
 	size_t		count)
 {
 	xfs_mount_t	*mp = ip->i_mount;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index 31c9108..4daaa52 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003,2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -29,9 +29,6 @@
  *
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
-
-
-
 #ifndef __XFS_IOMAP_H__
 #define __XFS_IOMAP_H__
 
@@ -56,7 +53,7 @@
 	BMAPI_UNWRITTEN  = (1 << 3),	/* unwritten extents to real extents */
 	/* modifiers */
 	BMAPI_IGNSTATE = (1 << 4),	/* ignore unwritten state on read */
-	BMAPI_DIRECT = (1 << 5),		/* direct instead of buffered write */
+	BMAPI_DIRECT = (1 << 5),	/* direct instead of buffered write */
 	BMAPI_MMAP = (1 << 6),		/* allocate for mmap write */
 	BMAPI_SYNC = (1 << 7),		/* sync write to flush delalloc space */
 	BMAPI_TRYLOCK = (1 << 8),	/* non-blocking request */
@@ -67,13 +64,13 @@
 /*
  * xfs_iomap_t:  File system I/O map
  *
- * The iomap_bn field is expressed in 512-byte blocks, and is where the 
+ * The iomap_bn field is expressed in 512-byte blocks, and is where the
  * mapping starts on disk.
  *
  * The iomap_offset, iomap_bsize and iomap_delta fields are in bytes.
  * iomap_offset is the offset of the mapping in the file itself.
- * iomap_bsize is the size of the mapping,  iomap_delta is the 
- * desired data's offset into the mapping, given the offset supplied 
+ * iomap_bsize is the size of the mapping,  iomap_delta is the
+ * desired data's offset into the mapping, given the offset supplied
  * to the file I/O map routine.
  *
  * When a request is made to read beyond the logical end of the object,
@@ -84,8 +81,8 @@
 typedef struct xfs_iomap {
 	xfs_daddr_t		iomap_bn;	/* first 512b blk of mapping */
 	xfs_buftarg_t		*iomap_target;
-	loff_t			iomap_offset;	/* offset of mapping, bytes */
-	loff_t			iomap_bsize;	/* size of mapping, bytes */
+	xfs_off_t		iomap_offset;	/* offset of mapping, bytes */
+	xfs_off_t		iomap_bsize;	/* size of mapping, bytes */
 	size_t			iomap_delta;	/* offset into mapping, bytes */
 	iomap_flags_t		iomap_flags;
 } xfs_iomap_t;
@@ -96,12 +93,12 @@
 
 extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
 		     struct xfs_iomap *, int *);
-extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t,
+extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
 				  int, struct xfs_bmbt_irec *, int *, int);
-extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int,
+extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, int,
 				 struct xfs_bmbt_irec *, int *);
-extern int xfs_iomap_write_allocate(struct xfs_inode *,
+extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t,
 				struct xfs_bmbt_irec *, int *);
-extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t);
+extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t);
 
 #endif /* __XFS_IOMAP_H__*/
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index b57423c..2ec967d 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -301,6 +301,15 @@
 	}
 
 	/*
+	 * Version 1 directory format has never worked on Linux.
+	 */
+	if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
+		cmn_err(CE_WARN,
+	"XFS: Attempted to mount file system using version 1 directory format");
+		return XFS_ERROR(ENOSYS);
+	}
+
+	/*
 	 * Until this is fixed only page-sized or smaller data blocks work.
 	 */
 	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 5fc6201..30dd08f 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -210,15 +210,16 @@
 				struct xfs_bmap_free *);
 typedef int		(*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
 typedef int		(*xfs_iomap_write_direct_t)(
-				void *, loff_t, size_t, int,
+				void *, xfs_off_t, size_t, int,
 				struct xfs_bmbt_irec *, int *, int);
 typedef int		(*xfs_iomap_write_delay_t)(
-				void *, loff_t, size_t, int,
+				void *, xfs_off_t, size_t, int,
 				struct xfs_bmbt_irec *, int *);
 typedef int		(*xfs_iomap_write_allocate_t)(
-				void *, struct xfs_bmbt_irec *, int *);
+				void *, xfs_off_t, size_t,
+				struct xfs_bmbt_irec *, int *);
 typedef int		(*xfs_iomap_write_unwritten_t)(
-				void *, loff_t, size_t);
+				void *, xfs_off_t, size_t);
 typedef uint		(*xfs_lck_map_shared_t)(void *);
 typedef void		(*xfs_lock_t)(void *, uint);
 typedef void		(*xfs_lock_demote_t)(void *, uint);
@@ -258,9 +259,9 @@
 #define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \
 	(*(mp)->m_io_ops.xfs_iomap_write_delay) \
 		((io)->io_obj, offset, count, flags, mval, nmap)
-#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, mval, nmap) \
+#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, mval, nmap) \
 	(*(mp)->m_io_ops.xfs_iomap_write_allocate) \
-		((io)->io_obj, mval, nmap)
+		((io)->io_obj, offset, count, mval, nmap)
 #define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \
 	(*(mp)->m_io_ops.xfs_iomap_write_unwritten) \
 		((io)->io_obj, offset, count)
@@ -428,10 +429,10 @@
 #define XFS_WRITEIO_LOG_LARGE	16
 
 /*
- * Max and min values for UIO and mount-option defined I/O sizes;
- * min value can't be less than a page.  Currently unused.
+ * Max and min values for mount-option defined I/O
+ * preallocation sizes.
  */
-#define XFS_MAX_IO_LOG		16	/* 64K */
+#define XFS_MAX_IO_LOG		30	/* 1G */
 #define XFS_MIN_IO_LOG		PAGE_SHIFT
 
 /*
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 04609d2..e4bf711 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -63,6 +63,7 @@
 typedef __s64			xfs_daddr_t;	/* <disk address> type */
 typedef char *			xfs_caddr_t;	/* <core address> type */
 typedef __u32			xfs_dev_t;
+typedef __u32			xfs_nlink_t;
 
 /* __psint_t is the same size as a pointer */
 #if (BITS_PER_LONG == 32)
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 816b945..d1f8146 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -147,7 +147,7 @@
 	xfs_inode_t	*dp,		/* directory within whose allocate
 					   the inode. */
 	mode_t		mode,
-	nlink_t		nlink,
+	xfs_nlink_t	nlink,
 	xfs_dev_t	rdev,
 	cred_t		*credp,
 	prid_t		prid,		/* project id */
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index e1ed6a5..01d98b4 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -42,7 +42,7 @@
 extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *,
 				xfs_inode_t **);
 extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
-extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, nlink_t,
+extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
 				xfs_dev_t, cred_t *, prid_t, int,
 				xfs_inode_t **, int *);
 extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 00aae9c..b537366 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1649,6 +1649,7 @@
 #define MNTOPT_SWIDTH	"swidth"	/* data volume stripe width */
 #define MNTOPT_NOUUID	"nouuid"	/* ignore filesystem UUID */
 #define MNTOPT_MTPT	"mtpt"		/* filesystem mount point */
+#define MNTOPT_ALLOCSIZE    "allocsize"    /* preferred allocation size */
 #define MNTOPT_IHASHSIZE    "ihashsize"    /* size of inode hash table */
 #define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */
 #define MNTOPT_NOLOGFLUSH   "nologflush"   /* don't hard flush on log writes */
@@ -1657,6 +1658,28 @@
 #define MNTOPT_IKEEP	"ikeep"		/* do not free empty inode clusters */
 #define MNTOPT_NOIKEEP	"noikeep"	/* free empty inode clusters */
 
+STATIC unsigned long
+suffix_strtoul(const char *cp, char **endp, unsigned int base)
+{
+	int	last, shift_left_factor = 0;
+	char	*value = (char *)cp;
+
+	last = strlen(value) - 1;
+	if (value[last] == 'K' || value[last] == 'k') {
+		shift_left_factor = 10;
+		value[last] = '\0';
+	}
+	if (value[last] == 'M' || value[last] == 'm') {
+		shift_left_factor = 20;
+		value[last] = '\0';
+	}
+	if (value[last] == 'G' || value[last] == 'g') {
+		shift_left_factor = 30;
+		value[last] = '\0';
+	}
+
+	return simple_strtoul(cp, endp, base) << shift_left_factor;
+}
 
 int
 xfs_parseargs(
@@ -1688,60 +1711,60 @@
 		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_LOGBUFS);
+					this_char);
 				return EINVAL;
 			}
 			args->logbufs = simple_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
-			int	last, in_kilobytes = 0;
-
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_LOGBSIZE);
+					this_char);
 				return EINVAL;
 			}
-			last = strlen(value) - 1;
-			if (value[last] == 'K' || value[last] == 'k') {
-				in_kilobytes = 1;
-				value[last] = '\0';
-			}
-			args->logbufsize = simple_strtoul(value, &eov, 10);
-			if (in_kilobytes)
-				args->logbufsize <<= 10;
+			args->logbufsize = suffix_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_LOGDEV);
+					this_char);
 				return EINVAL;
 			}
 			strncpy(args->logname, value, MAXNAMELEN);
 		} else if (!strcmp(this_char, MNTOPT_MTPT)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_MTPT);
+					this_char);
 				return EINVAL;
 			}
 			strncpy(args->mtpt, value, MAXNAMELEN);
 		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_RTDEV);
+					this_char);
 				return EINVAL;
 			}
 			strncpy(args->rtname, value, MAXNAMELEN);
 		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_BIOSIZE); 
+					this_char);
 				return EINVAL;
 			}
 			iosize = simple_strtoul(value, &eov, 10);
 			args->flags |= XFSMNT_IOSIZE;
 			args->iosizelog = (uint8_t) iosize;
+		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
+			if (!value || !*value) {
+				printk("XFS: %s option requires an argument\n",
+					this_char);
+				return EINVAL;
+			}
+			iosize = suffix_strtoul(value, &eov, 10);
+			args->flags |= XFSMNT_IOSIZE;
+			args->iosizelog = ffs(iosize) - 1;
 		} else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					this_char); 
+					this_char);
 				return EINVAL;
 			}
 			args->flags |= XFSMNT_IHASHSIZE;
@@ -1756,7 +1779,7 @@
 			args->flags |= XFSMNT_INO64;
 #if !XFS_BIG_INUMS
 			printk("XFS: %s option not allowed on this system\n",
-				MNTOPT_INO64);
+				this_char);
 			return EINVAL;
 #endif
 		} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
@@ -1766,14 +1789,14 @@
 		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_SUNIT);
+					this_char);
 				return EINVAL;
 			}
 			dsunit = simple_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
 			if (!value || !*value) {
 				printk("XFS: %s option requires an argument\n",
-					MNTOPT_SWIDTH);
+					this_char);
 				return EINVAL;
 			}
 			dswidth = simple_strtoul(value, &eov, 10);
@@ -1781,7 +1804,7 @@
 			args->flags &= ~XFSMNT_32BITINODES;
 #if !XFS_BIG_INUMS
 			printk("XFS: %s option not allowed on this system\n",
-				MNTOPT_64BITINODE);
+				this_char);
 			return EINVAL;
 #endif
 		} else if (!strcmp(this_char, MNTOPT_NOUUID)) {
@@ -1877,7 +1900,7 @@
 		seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
 
 	if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
-		seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log);
+		seq_printf(m, "," MNTOPT_ALLOCSIZE "=%d", 1<<mp->m_writeio_log);
 
 	if (mp->m_logbufs > 0)
 		seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 7009296..25a5266 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -305,7 +305,7 @@
 	int			mandlock_before, mandlock_after;
 	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
 	int			file_owner;
-	int			need_iolock = (flags & ATTR_DMI) == 0;
+	int			need_iolock = 1;
 
 	vp = BHV_TO_VNODE(bdp);
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -384,6 +384,9 @@
 	 */
 	tp = NULL;
 	lock_flags = XFS_ILOCK_EXCL;
+	ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
+	if (flags & ATTR_NOLOCK)
+		need_iolock = 0;
 	if (!(mask & XFS_AT_SIZE)) {
 		if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) ||
 		    (mp->m_flags & XFS_MOUNT_WSYNC)) {
@@ -4320,7 +4323,7 @@
 	int			rt;
 	xfs_fileoff_t		startoffset_fsb;
 	xfs_trans_t		*tp;
-	int			need_iolock = (attr_flags & ATTR_DMI) == 0;
+	int			need_iolock = 1;
 
 	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
 	mp = ip->i_mount;
@@ -4348,8 +4351,12 @@
 			return(error);
 	}
 
+	ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
+	if (attr_flags & ATTR_NOLOCK)
+		need_iolock = 0;
 	if (need_iolock)
 		xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
 	rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
 			(__uint8_t)NBPP);
 	ilen = len + (offset & (rounding - 1));
diff --git a/include/asm-alpha/bug.h b/include/asm-alpha/bug.h
index ae1e0a5..39a3e2a 100644
--- a/include/asm-alpha/bug.h
+++ b/include/asm-alpha/bug.h
@@ -1,6 +1,7 @@
 #ifndef _ALPHA_BUG_H
 #define _ALPHA_BUG_H
 
+#ifdef CONFIG_BUG
 #include <asm/pal.h>
 
 /* ??? Would be nice to use .gprel32 here, but we can't be sure that the
@@ -10,6 +11,8 @@
 		       : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-alpha/errno.h b/include/asm-alpha/errno.h
index c85ab6b..69e2655 100644
--- a/include/asm-alpha/errno.h
+++ b/include/asm-alpha/errno.h
@@ -116,4 +116,8 @@
 #define	EKEYREVOKED	134	/* Key has been revoked */
 #define	EKEYREJECTED	135	/* Key was rejected by service */
 
+/* for robust mutexes */
+#define	EOWNERDEAD	136	/* Owner died */
+#define	ENOTRECOVERABLE	137	/* State not recoverable */
+
 #endif
diff --git a/include/asm-alpha/siginfo.h b/include/asm-alpha/siginfo.h
index 86bcab5..9822362 100644
--- a/include/asm-alpha/siginfo.h
+++ b/include/asm-alpha/siginfo.h
@@ -4,8 +4,6 @@
 #define __ARCH_SI_PREAMBLE_SIZE		(4 * sizeof(int))
 #define __ARCH_SI_TRAPNO
 
-#define SIGEV_PAD_SIZE			((SIGEV_MAX_SIZE/sizeof(int)) - 4)
-
 #include <asm-generic/siginfo.h>
 
 #endif
diff --git a/include/asm-alpha/signal.h b/include/asm-alpha/signal.h
index 25f98bc..1a2c52a 100644
--- a/include/asm-alpha/signal.h
+++ b/include/asm-alpha/signal.h
@@ -109,34 +109,11 @@
 #define MINSIGSTKSZ	4096
 #define SIGSTKSZ	16384
 
-
-#ifdef __KERNEL__
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x40000000
-#endif
-
 #define SIG_BLOCK          1	/* for blocking signals */
 #define SIG_UNBLOCK        2	/* for unblocking signals */
 #define SIG_SETMASK        3	/* for setting the signal mask */
 
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct osf_sigaction {
diff --git a/include/asm-arm/arch-cl7500/vmalloc.h b/include/asm-arm/arch-cl7500/vmalloc.h
index 91883de..ba8d7a8 100644
--- a/include/asm-arm/arch-cl7500/vmalloc.h
+++ b/include/asm-arm/arch-cl7500/vmalloc.h
@@ -1,15 +1,4 @@
 /*
  * linux/include/asm-arm/arch-cl7500/vmalloc.h
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x1c000000)
diff --git a/include/asm-arm/arch-clps711x/vmalloc.h b/include/asm-arm/arch-clps711x/vmalloc.h
index 42571ed..a5dfe96 100644
--- a/include/asm-arm/arch-clps711x/vmalloc.h
+++ b/include/asm-arm/arch-clps711x/vmalloc.h
@@ -17,15 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-ebsa110/vmalloc.h b/include/asm-arm/arch-ebsa110/vmalloc.h
index 759659b..26674ba 100644
--- a/include/asm-arm/arch-ebsa110/vmalloc.h
+++ b/include/asm-arm/arch-ebsa110/vmalloc.h
@@ -7,15 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x1f000000)
diff --git a/include/asm-arm/arch-ebsa285/vmalloc.h b/include/asm-arm/arch-ebsa285/vmalloc.h
index def705a..d1ca955 100644
--- a/include/asm-arm/arch-ebsa285/vmalloc.h
+++ b/include/asm-arm/arch-ebsa285/vmalloc.h
@@ -8,17 +8,6 @@
 
 #include <linux/config.h>
 
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-
 #ifdef CONFIG_ARCH_FOOTBRIDGE
 #define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
 #else
diff --git a/include/asm-arm/arch-epxa10db/vmalloc.h b/include/asm-arm/arch-epxa10db/vmalloc.h
index d31ef85..546fb7d 100644
--- a/include/asm-arm/arch-epxa10db/vmalloc.h
+++ b/include/asm-arm/arch-epxa10db/vmalloc.h
@@ -17,15 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-h720x/vmalloc.h b/include/asm-arm/arch-h720x/vmalloc.h
index 4af523a..b4693cb 100644
--- a/include/asm-arm/arch-h720x/vmalloc.h
+++ b/include/asm-arm/arch-h720x/vmalloc.h
@@ -5,17 +5,6 @@
 #ifndef __ARCH_ARM_VMALLOC_H
 #define __ARCH_ARM_VMALLOC_H
 
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
 
 #endif
diff --git a/include/asm-arm/arch-imx/imxfb.h b/include/asm-arm/arch-imx/imxfb.h
new file mode 100644
index 0000000..2346d45
--- /dev/null
+++ b/include/asm-arm/arch-imx/imxfb.h
@@ -0,0 +1,35 @@
+/*
+ * This structure describes the machine which we are running on.
+ */
+struct imxfb_mach_info {
+	u_long		pixclock;
+
+	u_short		xres;
+	u_short		yres;
+
+	u_char		bpp;
+	u_char		hsync_len;
+	u_char		left_margin;
+	u_char		right_margin;
+
+	u_char		vsync_len;
+	u_char		upper_margin;
+	u_char		lower_margin;
+	u_char		sync;
+
+	u_int		cmap_greyscale:1,
+			cmap_inverse:1,
+			cmap_static:1,
+			unused:29;
+
+	u_int		pcr;
+	u_int		pwmr;
+	u_int		lscr1;
+
+	u_char * fixed_screen_cpu;
+	dma_addr_t fixed_screen_dma;
+
+	void (*lcd_power)(int);
+	void (*backlight_power)(int);
+};
+void set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info);
diff --git a/include/asm-arm/arch-imx/vmalloc.h b/include/asm-arm/arch-imx/vmalloc.h
index 252038f..cb61691 100644
--- a/include/asm-arm/arch-imx/vmalloc.h
+++ b/include/asm-arm/arch-imx/vmalloc.h
@@ -17,16 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-integrator/cm.h b/include/asm-arm/arch-integrator/cm.h
index d31c1a7..1ab353e 100644
--- a/include/asm-arm/arch-integrator/cm.h
+++ b/include/asm-arm/arch-integrator/cm.h
@@ -24,9 +24,9 @@
 #define CM_CTRL_LCDBIASDN		(1 << 10)
 #define CM_CTRL_LCDMUXSEL_MASK		(7 << 11)
 #define CM_CTRL_LCDMUXSEL_GENLCD	(1 << 11)
-#define CM_CTRL_LCDMUXSEL_SHARPLCD1	(3 << 11)
-#define CM_CTRL_LCDMUXSEL_SHARPLCD2	(4 << 11)
-#define CM_CTRL_LCDMUXSEL_VGA		(7 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA_16BPP	(2 << 11)
+#define CM_CTRL_LCDMUXSEL_SHARPLCD	(3 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA_8421BPP	(4 << 11)
 #define CM_CTRL_LCDEN0			(1 << 14)
 #define CM_CTRL_LCDEN1			(1 << 15)
 #define CM_CTRL_STATIC1			(1 << 16)
diff --git a/include/asm-arm/arch-integrator/platform.h b/include/asm-arm/arch-integrator/platform.h
index 6b67e41..bd364f5 100644
--- a/include/asm-arm/arch-integrator/platform.h
+++ b/include/asm-arm/arch-integrator/platform.h
@@ -20,14 +20,14 @@
  * * Copyright © ARM Limited 1998.  All rights reserved.
  * ***********************************************************************/
 /* ************************************************************************
- * 
+ *
  *   Integrator address map
- * 
+ *
  * 	NOTE: This is a multi-hosted header file for use with uHAL and
  * 	      supported debuggers.
- * 
+ *
  * 	$Id: platform.s,v 1.32 2000/02/18 10:51:39 asims Exp $
- * 
+ *
  * ***********************************************************************/
 
 #ifndef __address_h
@@ -40,22 +40,22 @@
  *  Memory definitions
  * ------------------------------------------------------------------------
  *  Integrator memory map
- * 
+ *
  */
 #define INTEGRATOR_BOOT_ROM_LO          0x00000000
 #define INTEGRATOR_BOOT_ROM_HI          0x20000000
 #define INTEGRATOR_BOOT_ROM_BASE        INTEGRATOR_BOOT_ROM_HI	 /*  Normal position */
 #define INTEGRATOR_BOOT_ROM_SIZE        SZ_512K
 
-/* 
+/*
  *  New Core Modules have different amounts of SSRAM, the amount of SSRAM
  *  fitted can be found in HDR_STAT.
- * 
+ *
  *  The symbol INTEGRATOR_SSRAM_SIZE is kept, however this now refers to
  *  the minimum amount of SSRAM fitted on any core module.
- * 
+ *
  *  New Core Modules also alias the SSRAM.
- * 
+ *
  */
 #define INTEGRATOR_SSRAM_BASE           0x00000000
 #define INTEGRATOR_SSRAM_ALIAS_BASE     0x10800000
@@ -67,9 +67,9 @@
 #define INTEGRATOR_MBRD_SSRAM_BASE      0x28000000
 #define INTEGRATOR_MBRD_SSRAM_SIZE      SZ_512K
 
-/* 
+/*
  *  SDRAM is a SIMM therefore the size is not known.
- * 
+ *
  */
 #define INTEGRATOR_SDRAM_BASE           0x00040000
 
@@ -79,9 +79,9 @@
 #define INTEGRATOR_HDR2_SDRAM_BASE      0xA0000000
 #define INTEGRATOR_HDR3_SDRAM_BASE      0xB0000000
 
-/* 
+/*
  *  Logic expansion modules
- * 
+ *
  */
 #define INTEGRATOR_LOGIC_MODULES_BASE   0xC0000000
 #define INTEGRATOR_LOGIC_MODULE0_BASE   0xC0000000
@@ -92,7 +92,7 @@
 /* ------------------------------------------------------------------------
  *  Integrator header card registers
  * ------------------------------------------------------------------------
- * 
+ *
  */
 #define INTEGRATOR_HDR_ID_OFFSET        0x00
 #define INTEGRATOR_HDR_PROC_OFFSET      0x04
@@ -185,12 +185,12 @@
 /* ------------------------------------------------------------------------
  *  Integrator system registers
  * ------------------------------------------------------------------------
- * 
+ *
  */
 
-/* 
+/*
  *  System Controller
- * 
+ *
  */
 #define INTEGRATOR_SC_ID_OFFSET         0x00
 #define INTEGRATOR_SC_OSC_OFFSET        0x04
@@ -230,11 +230,11 @@
 #define INTEGRATOR_SC_CTRL_URTS1        (1 << 6)
 #define INTEGRATOR_SC_CTRL_UDTR1        (1 << 7)
 
-/* 
+/*
  *  External Bus Interface
- * 
+ *
  */
-#define INTEGRATOR_EBI_BASE             0x12000000 
+#define INTEGRATOR_EBI_BASE             0x12000000
 
 #define INTEGRATOR_EBI_CSR0_OFFSET      0x00
 #define INTEGRATOR_EBI_CSR1_OFFSET      0x04
@@ -279,9 +279,9 @@
 #define INTEGRATOR_KBD_BASE             0x18000000	 /*  Keyboard */
 #define INTEGRATOR_MOUSE_BASE           0x19000000	 /*  Mouse */
 
-/* 
+/*
  *  LED's & Switches
- * 
+ *
  */
 #define INTEGRATOR_DBG_ALPHA_OFFSET     0x00
 #define INTEGRATOR_DBG_LEDS_OFFSET      0x04
@@ -300,7 +300,7 @@
  * ------------------------------------------------------------------------
  */
 /* PS2 Keyboard interface */
-#define KMI0_BASE                       INTEGRATOR_KBD_BASE		
+#define KMI0_BASE                       INTEGRATOR_KBD_BASE
 
 /* PS2 Mouse interface */
 #define KMI1_BASE                       INTEGRATOR_MOUSE_BASE
@@ -313,7 +313,7 @@
  *  This represents a fairly liberal usage of address space.  Even though
  *  the V3 only has two windows (therefore we need to map stuff on the fly),
  *  we maintain the same addresses, even if they're not mapped.
- * 
+ *
  */
 #define PHYS_PCI_MEM_BASE               0x40000000   /* 512M to xxx */
 /*  unused 256M from A0000000-AFFFFFFF might be used for I2O ???
@@ -326,7 +326,7 @@
  */
 #define PHYS_PCI_V3_BASE                0x62000000
 
-#define PCI_DRAMSIZE                    INTEGRATOR_SSRAM_SIZE	
+#define PCI_DRAMSIZE                    INTEGRATOR_SSRAM_SIZE
 
 /* 'export' these to UHAL */
 #define UHAL_PCI_IO                     PCI_IO_BASE
@@ -334,7 +334,7 @@
 #define UHAL_PCI_ALLOC_IO_BASE          0x00004000
 #define UHAL_PCI_ALLOC_MEM_BASE         PCI_MEM_BASE
 #define UHAL_PCI_MAX_SLOT               20
-	
+
 /* ========================================================================
  *  Start of uHAL definitions
  * ========================================================================
@@ -343,17 +343,17 @@
 /* ------------------------------------------------------------------------
  *  Integrator Interrupt Controllers
  * ------------------------------------------------------------------------
- * 
- *  Offsets from interrupt controller base 
- * 
+ *
+ *  Offsets from interrupt controller base
+ *
  *  System Controller interrupt controller base is
- * 
+ *
  * 	INTEGRATOR_IC_BASE + (header_number << 6)
- * 
+ *
  *  Core Module interrupt controller base is
- * 
- * 	INTEGRATOR_HDR_IC 
- * 
+ *
+ * 	INTEGRATOR_HDR_IC
+ *
  */
 #define IRQ_STATUS                      0
 #define IRQ_RAW_STATUS                  0x04
@@ -374,22 +374,22 @@
 /* ------------------------------------------------------------------------
  *  Interrupts
  * ------------------------------------------------------------------------
- * 
- *  
+ *
+ *
  *  Each Core Module has two interrupts controllers, one on the core module
  *  itself and one in the system controller on the motherboard.  The
  *  READ_INT macro in target.s reads both interrupt controllers and returns
  *  a 32 bit bitmask, bits 0 to 23 are interrupts from the system controller
  *  and bits 24 to 31 are from the core module.
- *  
+ *
  *  The following definitions relate to the bitmask returned by READ_INT.
- * 
+ *
  */
 
 /* ------------------------------------------------------------------------
  *  LED's - The header LED is not accessible via the uHAL API
  * ------------------------------------------------------------------------
- * 
+ *
  */
 #define GREEN_LED                       0x01
 #define YELLOW_LED                      0x02
@@ -399,44 +399,44 @@
 
 #define LED_BANK                        INTEGRATOR_DBG_LEDS
 
-/* 
+/*
  *  Memory definitions - run uHAL out of SSRAM.
- * 
+ *
  */
 #define uHAL_MEMORY_SIZE                INTEGRATOR_SSRAM_SIZE
 
-/* 
+/*
  *  Application Flash
- * 
+ *
  */
 #define FLASH_BASE                      INTEGRATOR_FLASH_BASE
 #define FLASH_SIZE                      INTEGRATOR_FLASH_SIZE
 #define FLASH_END                       (FLASH_BASE + FLASH_SIZE - 1)
 #define FLASH_BLOCK_SIZE                SZ_128K
 
-/* 
+/*
  *  Boot Flash
- * 
+ *
  */
 #define EPROM_BASE                      INTEGRATOR_BOOT_ROM_HI
 #define EPROM_SIZE                      INTEGRATOR_BOOT_ROM_SIZE
 #define EPROM_END                       (EPROM_BASE + EPROM_SIZE - 1)
 
-/* 
+/*
  *  Clean base - dummy
- * 
+ *
  */
 #define CLEAN_BASE                      EPROM_BASE
 
-/* 
+/*
  *  Timer definitions
- * 
+ *
  *  Only use timer 1 & 2
  *  (both run at 24MHz and will need the clock divider set to 16).
- * 
+ *
  *  Timer 0 runs at bus frequency and therefore could vary and currently
  *  uHAL can't handle that.
- * 
+ *
  */
 
 #define INTEGRATOR_TIMER0_BASE          INTEGRATOR_CT_BASE
@@ -447,9 +447,9 @@
 #define MAX_PERIOD                      699050
 #define TICKS_PER_uSEC                  24
 
-/* 
- *  These are useconds NOT ticks.  
- * 
+/*
+ *  These are useconds NOT ticks.
+ *
  */
 #define mSEC_1                          1000
 #define mSEC_5                          (mSEC_1 * 5)
diff --git a/include/asm-arm/arch-integrator/vmalloc.h b/include/asm-arm/arch-integrator/vmalloc.h
index 50e9aee..170ccce 100644
--- a/include/asm-arm/arch-integrator/vmalloc.h
+++ b/include/asm-arm/arch-integrator/vmalloc.h
@@ -17,15 +17,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-iop3xx/vmalloc.h b/include/asm-arm/arch-iop3xx/vmalloc.h
index dc1d2a9..0f2f684 100644
--- a/include/asm-arm/arch-iop3xx/vmalloc.h
+++ b/include/asm-arm/arch-iop3xx/vmalloc.h
@@ -10,9 +10,6 @@
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 //#define VMALLOC_END       (0xe8000000)
 /* increase usable physical RAM to ~992M per RMK */
 #define VMALLOC_END       (0xfe000000)
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index 509e44d..901bba6 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -121,6 +121,7 @@
 
 struct pci_sys_data;
 
+u32 *ixp2000_pci_config_addr(unsigned int bus, unsigned int devfn, int where);
 void ixp2000_pci_preinit(void);
 int ixp2000_pci_setup(int, struct pci_sys_data*);
 struct pci_bus* ixp2000_pci_scan_bus(int, struct pci_sys_data*);
diff --git a/include/asm-arm/arch-ixp2000/vmalloc.h b/include/asm-arm/arch-ixp2000/vmalloc.h
index 2e4bcbc..473dff4 100644
--- a/include/asm-arm/arch-ixp2000/vmalloc.h
+++ b/include/asm-arm/arch-ixp2000/vmalloc.h
@@ -17,7 +17,4 @@
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
-#define VMALLOC_OFFSET	    (8*1024*1024)
-#define VMALLOC_START	    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x)   ((unsigned long)(x))
 #define VMALLOC_END	    0xfaffefff
diff --git a/include/asm-arm/arch-ixp4xx/vmalloc.h b/include/asm-arm/arch-ixp4xx/vmalloc.h
index da46e56..050d46e 100644
--- a/include/asm-arm/arch-ixp4xx/vmalloc.h
+++ b/include/asm-arm/arch-ixp4xx/vmalloc.h
@@ -1,17 +1,5 @@
 /*
  * linux/include/asm-arm/arch-ixp4xx/vmalloc.h
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (0xFF000000)
 
diff --git a/include/asm-arm/arch-l7200/vmalloc.h b/include/asm-arm/arch-l7200/vmalloc.h
index edeaebe..816231e 100644
--- a/include/asm-arm/arch-l7200/vmalloc.h
+++ b/include/asm-arm/arch-l7200/vmalloc.h
@@ -1,15 +1,4 @@
 /*
  * linux/include/asm-arm/arch-l7200/vmalloc.h
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-lh7a40x/vmalloc.h b/include/asm-arm/arch-lh7a40x/vmalloc.h
index 5ac6079..8163e45 100644
--- a/include/asm-arm/arch-lh7a40x/vmalloc.h
+++ b/include/asm-arm/arch-lh7a40x/vmalloc.h
@@ -7,15 +7,4 @@
  *  version 2 as published by the Free Software Foundation.
  *
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after
- * the physical memory until the kernel virtual memory starts.  That
- * means that any out-of-bounds memory accesses will hopefully be
- * caught.  The vmalloc() routines leaves a hole of 4kB (one page)
- * between each vmalloced area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (0xe8000000)
diff --git a/include/asm-arm/arch-omap/vmalloc.h b/include/asm-arm/arch-omap/vmalloc.h
index c6a8358..5b8bd8d 100644
--- a/include/asm-arm/arch-omap/vmalloc.h
+++ b/include/asm-arm/arch-omap/vmalloc.h
@@ -17,17 +17,5 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END	  (PAGE_OFFSET + 0x10000000)
 
diff --git a/include/asm-arm/arch-pxa/vmalloc.h b/include/asm-arm/arch-pxa/vmalloc.h
index 3381af6..5bb450c 100644
--- a/include/asm-arm/arch-pxa/vmalloc.h
+++ b/include/asm-arm/arch-pxa/vmalloc.h
@@ -8,15 +8,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (0xe8000000)
diff --git a/include/asm-arm/arch-rpc/vmalloc.h b/include/asm-arm/arch-rpc/vmalloc.h
index a13c27f..077046b 100644
--- a/include/asm-arm/arch-rpc/vmalloc.h
+++ b/include/asm-arm/arch-rpc/vmalloc.h
@@ -7,15 +7,4 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x1c000000)
diff --git a/include/asm-arm/arch-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h
index 7ae8e1f..385b07d 100644
--- a/include/asm-arm/arch-s3c2410/regs-iis.h
+++ b/include/asm-arm/arch-s3c2410/regs-iis.h
@@ -14,6 +14,7 @@
  *    26-06-2003     BJD     Finished off definitions for register addresses
  *    12-03-2004     BJD     Updated include protection
  *    07-03-2005     BJD     Added FIFO size flags and S3C2440 MPLL
+ *    05-04-2005     LCVR    Added IISFCON definitions for the S3C2400
  */
 
 #ifndef __ASM_ARCH_REGS_IIS_H
@@ -68,5 +69,14 @@
 #define S3C2410_IISFCON_RXMASK	  (0x3f)
 #define S3C2410_IISFCON_RXSHIFT	  (0)
 
+#define S3C2400_IISFCON_TXDMA     (1<<11)
+#define S3C2400_IISFCON_RXDMA     (1<<10)
+#define S3C2400_IISFCON_TXENABLE  (1<<9)
+#define S3C2400_IISFCON_RXENABLE  (1<<8)
+#define S3C2400_IISFCON_TXMASK	  (0x07 << 4)
+#define S3C2400_IISFCON_TXSHIFT	  (4)
+#define S3C2400_IISFCON_RXMASK	  (0x07)
+#define S3C2400_IISFCON_RXSHIFT	  (0)
+
 #define S3C2410_IISFIFO  (0x10)
 #endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
index 1a1328a..a2d7d0c 100644
--- a/include/asm-arm/arch-s3c2410/regs-mem.h
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h
@@ -12,6 +12,7 @@
  *  Changelog:
  *	29-Sep-2004  BJD  Initial include for Linux
  *      10-Mar-2005  LCVR Changed S3C2410_VA to S3C24XX_VA
+ *      04-Apr-2005  LCVR Added S3C2400 DRAM/BANKSIZE_MASK definitions
  *
 */
 
@@ -183,6 +184,12 @@
 #define S3C2410_REFRESH_TRP_3clk	(1<<20)
 #define S3C2410_REFRESH_TRP_4clk	(2<<20)
 
+#define S3C2400_REFRESH_DRAM_TRP_MASK   (3<<20)
+#define S3C2400_REFRESH_DRAM_TRP_1_5clk (0<<20)
+#define S3C2400_REFRESH_DRAM_TRP_2_5clk (1<<20)
+#define S3C2400_REFRESH_DRAM_TRP_3_5clk (2<<20)
+#define S3C2400_REFRESH_DRAM_TRP_4_5clk (3<<20)
+
 #define S3C2410_REFRESH_TSRC_MASK	(3<<18)
 #define S3C2410_REFRESH_TSRC_4clk	(0<<18)
 #define S3C2410_REFRESH_TSRC_5clk	(1<<18)
@@ -205,6 +212,7 @@
 #define S3C2410_BANKSIZE_4M		(0x5 << 0)
 #define S3C2410_BANKSIZE_2M		(0x4 << 0)
 #define S3C2410_BANKSIZE_MASK		(0x7 << 0)
+#define S3C2400_BANKSIZE_MASK           (0x4 << 0)
 #define S3C2410_BANKSIZE_SCLK_EN	(1<<4)
 #define S3C2410_BANKSIZE_SCKE_EN	(1<<5)
 #define S3C2410_BANKSIZE_BURST		(1<<7)
diff --git a/include/asm-arm/arch-s3c2410/regs-spi.h b/include/asm-arm/arch-s3c2410/regs-spi.h
index cb502a8..3382178 100644
--- a/include/asm-arm/arch-s3c2410/regs-spi.h
+++ b/include/asm-arm/arch-s3c2410/regs-spi.h
@@ -12,6 +12,7 @@
  *    20-04-2004     KF      Created file
  *    04-10-2004     BJD     Removed VA address (no longer mapped)
  *			     tidied file for submission
+ *    03-04-2005     LCVR    Added S3C2400_SPPIN_nCS definition
  */
 
 #ifndef __ASM_ARCH_REGS_SPI_H
@@ -46,6 +47,7 @@
 
 #define S3C2410_SPPIN_ENMUL	  (1<<2)	/* Multi Master Error detect */
 #define S3C2410_SPPIN_RESERVED	  (1<<1)
+#define S3C2400_SPPIN_nCS     	  (1<<1)	/* SPI Card Select */
 #define S3C2410_SPPIN_KEEP	  (1<<0)	/* Master Out keep */
 
 
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index ad4252e..d7a4a83 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -16,6 +16,7 @@
  *  12-Oct-2004 BJD  Take account of debug uart configuration
  *  15-Nov-2004 BJD  Fixed uart configuration
  *  22-Feb-2005 BJD  Added watchdog to uncompress
+ *  04-Apr-2005 LCVR Added support to S3C2400 (no cpuid at GSTATUS1)
 */
 
 #ifndef __ASM_ARCH_UNCOMPRESS_H
@@ -69,9 +70,12 @@
 static void
 putc(char ch)
 {
-	int cpuid = *((volatile unsigned int *)S3C2410_GSTATUS1);
+	int cpuid = S3C2410_GSTATUS1_2410;
 
+#ifndef CONFIG_CPU_S3C2400
+	cpuid = *((volatile unsigned int *)S3C2410_GSTATUS1);
 	cpuid &= S3C2410_GSTATUS1_IDMASK;
+#endif
 
 	if (ch == '\n')
 		putc('\r');    /* expand newline to \r\n */
diff --git a/include/asm-arm/arch-s3c2410/vmalloc.h b/include/asm-arm/arch-s3c2410/vmalloc.h
index 5fe72ad..33963cd 100644
--- a/include/asm-arm/arch-s3c2410/vmalloc.h
+++ b/include/asm-arm/arch-s3c2410/vmalloc.h
@@ -19,18 +19,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END	  (0xE0000000)
 
 #endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/include/asm-arm/arch-sa1100/vmalloc.h b/include/asm-arm/arch-sa1100/vmalloc.h
index 135bc94..2fb1c6f 100644
--- a/include/asm-arm/arch-sa1100/vmalloc.h
+++ b/include/asm-arm/arch-sa1100/vmalloc.h
@@ -1,15 +1,4 @@
 /*
  * linux/include/asm-arm/arch-sa1100/vmalloc.h
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (0xe8000000)
diff --git a/include/asm-arm/arch-shark/vmalloc.h b/include/asm-arm/arch-shark/vmalloc.h
index 1cc2009..10db5d1 100644
--- a/include/asm-arm/arch-shark/vmalloc.h
+++ b/include/asm-arm/arch-shark/vmalloc.h
@@ -1,15 +1,4 @@
 /*
  * linux/include/asm-arm/arch-rpc/vmalloc.h
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET	  (8*1024*1024)
-#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-versatile/vmalloc.h b/include/asm-arm/arch-versatile/vmalloc.h
index adfb3482..ac780df 100644
--- a/include/asm-arm/arch-versatile/vmalloc.h
+++ b/include/asm-arm/arch-versatile/vmalloc.h
@@ -18,16 +18,4 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
-/*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_OFFSET		(8*1024*1024)
-#define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_VMADDR(x)	((unsigned long)(x))
 #define VMALLOC_END		(PAGE_OFFSET + 0x18000000)
diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h
index 5e91b90..24d1167 100644
--- a/include/asm-arm/bug.h
+++ b/include/asm-arm/bug.h
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern volatile void __bug(const char *file, int line, void *data);
 
@@ -17,6 +18,8 @@
 #endif
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-arm/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h
index 2149be7..ce4cf5c 100644
--- a/include/asm-arm/hardware/amba_clcd.h
+++ b/include/asm-arm/hardware/amba_clcd.h
@@ -153,7 +153,7 @@
 
 static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
 {
-	u32 val;
+	u32 val, cpl;
 
 	/*
 	 * Program the CLCD controller registers and start the CLCD
@@ -164,7 +164,10 @@
 	val |= (fb->fb.var.left_margin - 1) << 24;
 	regs->tim0 = val;
 
-	val = fb->fb.var.yres - 1;
+	val = fb->fb.var.yres;
+	if (fb->panel->cntl & CNTL_LCDDUAL)
+		val /= 2;
+	val -= 1;
 	val |= (fb->fb.var.vsync_len - 1) << 10;
 	val |= fb->fb.var.lower_margin << 16;
 	val |= fb->fb.var.upper_margin << 24;
@@ -174,13 +177,17 @@
 	val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
 	val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
 
-	if (fb->panel->cntl & CNTL_LCDTFT)
-		val |= (fb->fb.var.xres_virtual - 1) << 16;
-	else if (fb->panel->cntl & CNTL_LCDBW)
-		printk("what value for CPL for stnmono panels?");
-	else
-		val |= ((fb->fb.var.xres_virtual * 8 / 3) - 1) << 16;
-	regs->tim2 = val;
+	cpl = fb->fb.var.xres_virtual;
+	if (fb->panel->cntl & CNTL_LCDTFT)	  /* TFT */
+		/* / 1 */;
+	else if (!fb->fb.var.grayscale)		  /* STN color */
+		cpl = cpl * 8 / 3;
+	else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */
+		cpl /= 8;
+	else					  /* STN monochrome, 4bit */
+		cpl /= 4;
+
+	regs->tim2 = val | ((cpl - 1) << 16);
 
 	regs->tim3 = fb->panel->tim3;
 
@@ -204,7 +211,7 @@
 	case 16:
 		val |= CNTL_LCDBPP16;
 		break;
-	case 24:
+	case 32:
 		val |= CNTL_LCDBPP24;
 		break;
 	}
@@ -215,8 +222,8 @@
 
 static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
 {
-	var->xres_virtual = var->xres = (var->xres + 7) & ~7;
-	var->yres_virtual = var->yres;
+	var->xres_virtual = var->xres = (var->xres + 15) & ~15;
+	var->yres_virtual = var->yres = (var->yres + 1) & ~1;
 
 #define CHECK(e,l,h) (var->e < l || var->e > h)
 	if (CHECK(right_margin, (5+1), 256) ||	/* back porch */
diff --git a/include/asm-arm/hardware/clock.h b/include/asm-arm/hardware/clock.h
index 4983449..19da861 100644
--- a/include/asm-arm/hardware/clock.h
+++ b/include/asm-arm/hardware/clock.h
@@ -26,10 +26,13 @@
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
- * @id: device ID
+ * @id: clock comsumer ID
  *
  * Returns a struct clk corresponding to the clock producer, or
- * valid IS_ERR() condition containing errno.
+ * valid IS_ERR() condition containing errno.  The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer.  (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
  */
 struct clk *clk_get(struct device *dev, const char *id);
 
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 69bc7a3..658ffa3 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -99,12 +99,16 @@
  */
 #ifdef __io
 #define outb(v,p)		__raw_writeb(v,__io(p))
-#define outw(v,p)		__raw_writew(cpu_to_le16(v),__io(p))
-#define outl(v,p)		__raw_writel(cpu_to_le32(v),__io(p))
+#define outw(v,p)		__raw_writew((__force __u16) \
+					cpu_to_le16(v),__io(p))
+#define outl(v,p)		__raw_writel((__force __u32) \
+					cpu_to_le32(v),__io(p))
 
-#define inb(p)	({ unsigned int __v = __raw_readb(__io(p)); __v; })
-#define inw(p)	({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
-#define inl(p)	({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
+#define inb(p)	({ __u8 __v = __raw_readb(__io(p)); __v; })
+#define inw(p)	({ __u16 __v = le16_to_cpu((__force __le16) \
+			__raw_readw(__io(p))); __v; })
+#define inl(p)	({ __u32 __v = le32_to_cpu((__force __le32) \
+			__raw_readl(__io(p))); __v; })
 
 #define outsb(p,d,l)		__raw_writesb(__io(p),d,l)
 #define outsw(p,d,l)		__raw_writesw(__io(p),d,l)
@@ -149,9 +153,11 @@
  * IO port primitives for more information.
  */
 #ifdef __mem_pci
-#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
-#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
-#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
+#define readb(c) ({ __u8  __v = __raw_readb(__mem_pci(c)); __v; })
+#define readw(c) ({ __u16 __v = le16_to_cpu((__force __le16) \
+					__raw_readw(__mem_pci(c))); __v; })
+#define readl(c) ({ __u32 __v = le32_to_cpu((__force __le32) \
+					__raw_readl(__mem_pci(c))); __v; })
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
@@ -161,8 +167,10 @@
 #define readsl(p,d,l)		__raw_readsl(__mem_pci(p),d,l)
 
 #define writeb(v,c)		__raw_writeb(v,__mem_pci(c))
-#define writew(v,c)		__raw_writew(cpu_to_le16(v),__mem_pci(c))
-#define writel(v,c)		__raw_writel(cpu_to_le32(v),__mem_pci(c))
+#define writew(v,c)		__raw_writew((__force __u16) \
+					cpu_to_le16(v),__mem_pci(c))
+#define writel(v,c)		__raw_writel((__force __u32) \
+					cpu_to_le32(v),__mem_pci(c))
 
 #define writesb(p,d,l)		__raw_writesb(__mem_pci(p),d,l)
 #define writesw(p,d,l)		__raw_writesw(__mem_pci(p),d,l)
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 2df4eac..a9892eb 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -17,6 +17,23 @@
 #include <asm/arch/vmalloc.h>
 
 /*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ *
+ * Note that platforms may override VMALLOC_START, but they must provide
+ * VMALLOC_END.  VMALLOC_END defines the (exclusive) limit of this space,
+ * which may not overlap IO space.
+ */
+#ifndef VMALLOC_START
+#define VMALLOC_OFFSET		(8*1024*1024)
+#define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#endif
+
+/*
  * Hardware-wise, we have a two level page table structure, where the first
  * level has 4096 entries, and the second level has 256 entries.  Each entry
  * is one 32-bit word.  Most of the bits in the second level entry are used
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index 4a98459..7d4118e 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -23,8 +23,6 @@
 #include <asm/procinfo.h>
 #include <asm/types.h>
 
-#define KERNEL_STACK_SIZE	PAGE_SIZE
-
 union debug_insn {
 	u32	arm;
 	u16	thumb;
@@ -87,8 +85,9 @@
  */
 extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
-#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019])
-#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1017])
+#define KSTK_REGS(tsk)	(((struct pt_regs *)(THREAD_START_SP + (unsigned long)(tsk)->thread_info)) - 1)
+#define KSTK_EIP(tsk)	KSTK_REGS(tsk)->ARM_pc
+#define KSTK_ESP(tsk)	KSTK_REGS(tsk)->ARM_sp
 
 /*
  * Prefetching support - only ARMv5.
diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h
index aa7e16b..370dfe7 100644
--- a/include/asm-arm/rtc.h
+++ b/include/asm-arm/rtc.h
@@ -18,9 +18,9 @@
 	void		(*release)(void);
 	int		(*ioctl)(unsigned int, unsigned long);
 
-	void		(*read_time)(struct rtc_time *);
+	int		(*read_time)(struct rtc_time *);
 	int		(*set_time)(struct rtc_time *);
-	void		(*read_alarm)(struct rtc_wkalrm *);
+	int		(*read_alarm)(struct rtc_wkalrm *);
 	int		(*set_alarm)(struct rtc_wkalrm *);
 	int		(*proc)(char *buf);
 };
diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h
index b033e5f..46e69ae 100644
--- a/include/asm-arm/signal.h
+++ b/include/asm-arm/signal.h
@@ -114,34 +114,10 @@
 #define SIGSTKSZ	8192
 
 #ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		0x80000000
-#define SA_SAMPLE_RANDOM	0x10000000
 #define SA_IRQNOMASK		0x08000000
-#define SA_SHIRQ		0x04000000
 #endif
 
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-arm/string.h b/include/asm-arm/string.h
index 2a8ab16..e50c4a3 100644
--- a/include/asm-arm/string.h
+++ b/include/asm-arm/string.h
@@ -29,15 +29,22 @@
 
 #define memset(p,v,n)							\
 	({								\
-		if ((n) != 0) {						\
+	 	void *__p = (p); size_t __n = n;			\
+		if ((__n) != 0) {					\
 			if (__builtin_constant_p((v)) && (v) == 0)	\
-				__memzero((p),(n));			\
+				__memzero((__p),(__n));			\
 			else						\
-				memset((p),(v),(n));			\
+				memset((__p),(v),(__n));		\
 		}							\
-		(p);							\
+		(__p);							\
 	})
 
-#define memzero(p,n) ({ if ((n) != 0) __memzero((p),(n)); (p); })
+#define memzero(p,n) 							\
+	({ 								\
+	 	void *__p = (p); size_t __n = n;			\
+	 	if ((__n) != 0) 					\
+	 		__memzero((__p),(__n)); 			\
+	 	(__p); 							\
+	 })
 
 #endif
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index a61618f..66c585c 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -14,6 +14,10 @@
 
 #include <asm/fpstate.h>
 
+#define THREAD_SIZE_ORDER	1
+#define THREAD_SIZE		8192
+#define THREAD_START_SP		(THREAD_SIZE - 8)
+
 #ifndef __ASSEMBLY__
 
 struct task_struct;
@@ -77,8 +81,6 @@
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-#define THREAD_SIZE		8192
-
 /*
  * how to get the thread information struct from C
  */
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index a19ec09..ace2748 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -359,8 +359,7 @@
 #define __ARM_NR_cacheflush		(__ARM_NR_BASE+2)
 #define __ARM_NR_usr26			(__ARM_NR_BASE+3)
 #define __ARM_NR_usr32			(__ARM_NR_BASE+4)
-
-#define __ARM_NR_set_tls		(__ARM_NR_BASE+0x800)
+#define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
diff --git a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h
index 920b705..7177c73 100644
--- a/include/asm-arm26/bug.h
+++ b/include/asm-arm26/bug.h
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern volatile void __bug(const char *file, int line, void *data);
 /* give file/line information */
@@ -12,6 +13,8 @@
 #endif
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-arm26/signal.h b/include/asm-arm26/signal.h
index 6f62e51..dedb292 100644
--- a/include/asm-arm26/signal.h
+++ b/include/asm-arm26/signal.h
@@ -114,30 +114,10 @@
 #define SIGSTKSZ	8192
 
 #ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		0x80000000
-#define SA_SAMPLE_RANDOM	0x10000000
 #define SA_IRQNOMASK		0x08000000
-#define SA_SHIRQ		0x04000000
 #endif
 
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index ddd8915..c767da1 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -77,10 +77,6 @@
   printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
 } while (0)
 
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
 /* Pure 2^n version of get_order */
 static inline int get_order(unsigned long size)
 {
diff --git a/include/asm-cris/signal.h b/include/asm-cris/signal.h
index 3f187ec..dfe0395 100644
--- a/include/asm-cris/signal.h
+++ b/include/asm-cris/signal.h
@@ -108,30 +108,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-frv/bug.h b/include/asm-frv/bug.h
index 011860b..074c0d5 100644
--- a/include/asm-frv/bug.h
+++ b/include/asm-frv/bug.h
@@ -13,6 +13,7 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_BUG
 /*
  * Tell the user there is some problem.
  */
@@ -45,6 +46,7 @@
 #define HAVE_ARCH_KGDB_BAD_PAGE
 #define kgdb_bad_page(page) do { kgdb_raise(SIGABRT); } while(0)
 #endif
+#endif
 
 #include <asm-generic/bug.h>
 
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 3c6d42a..d0a9c2f 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -349,9 +349,9 @@
 
 /*
  * Define this to warn about kernel memory accesses that are
- * done without a 'verify_area(VERIFY_WRITE,..)'
+ * done without a 'access_ok(VERIFY_WRITE,..)'
  */
-#undef TEST_VERIFY_AREA
+#undef TEST_ACCESS_OK
 
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
 #define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
diff --git a/include/asm-frv/signal.h b/include/asm-frv/signal.h
index f18952f..d407bde 100644
--- a/include/asm-frv/signal.h
+++ b/include/asm-frv/signal.h
@@ -107,30 +107,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index e5913c3..400c2b4 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -4,6 +4,7 @@
 #include <linux/compiler.h>
 #include <linux/config.h>
 
+#ifdef CONFIG_BUG
 #ifndef HAVE_ARCH_BUG
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
@@ -11,13 +12,6 @@
 } while (0)
 #endif
 
-#ifndef HAVE_ARCH_PAGE_BUG
-#define PAGE_BUG(page) do { \
-	printk("page BUG for page at %p\n", page); \
-	BUG(); \
-} while (0)
-#endif
-
 #ifndef HAVE_ARCH_BUG_ON
 #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #endif
@@ -31,4 +25,18 @@
 } while (0)
 #endif
 
+#else /* !CONFIG_BUG */
+#ifndef HAVE_ARCH_BUG
+#define BUG()
+#endif
+
+#ifndef HAVE_ARCH_BUG_ON
+#define BUG_ON(condition) do { if (condition) ; } while(0)
+#endif
+
+#ifndef HAVE_ARCH_WARN_ON
+#define WARN_ON(condition) do { if (condition) ; } while(0)
+#endif
+#endif
+
 #endif
diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h
index 4dd2384..e8852c0 100644
--- a/include/asm-generic/errno.h
+++ b/include/asm-generic/errno.h
@@ -102,4 +102,8 @@
 #define	EKEYREVOKED	128	/* Key has been revoked */
 #define	EKEYREJECTED	129	/* Key was rejected by service */
 
+/* for robust mutexes */
+#define	EOWNERDEAD	130	/* Owner died */
+#define	ENOTRECOVERABLE	131	/* State not recoverable */
+
 #endif
diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
index b1fcda9..cfe3692 100644
--- a/include/asm-generic/resource.h
+++ b/include/asm-generic/resource.h
@@ -41,8 +41,11 @@
 #define RLIMIT_LOCKS		10	/* maximum file locks held */
 #define RLIMIT_SIGPENDING	11	/* max number of pending signals */
 #define RLIMIT_MSGQUEUE		12	/* maximum bytes in POSIX mqueues */
+#define RLIMIT_NICE		13	/* max nice prio allowed to raise to
+					   0-39 for nice level 19 .. -20 */
+#define RLIMIT_RTPRIO		14	/* maximum realtime priority */
 
-#define RLIM_NLIMITS		13
+#define RLIM_NLIMITS		15
 
 /*
  * SuS says limits have to be unsigned.
@@ -81,6 +84,8 @@
 	[RLIMIT_LOCKS]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
 	[RLIMIT_SIGPENDING]	= { 		0,	       0 },	\
 	[RLIMIT_MSGQUEUE]	= {   MQ_BYTES_MAX,   MQ_BYTES_MAX },	\
+	[RLIMIT_NICE]		= { 0, 0 },				\
+	[RLIMIT_RTPRIO]		= { 0, 0 },				\
 }
 
 #endif	/* __KERNEL__ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 976ac29..195ccdc 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -8,6 +8,8 @@
 extern char __bss_start[], __bss_stop[];
 extern char __init_begin[], __init_end[];
 extern char _sinittext[], _einittext[];
+extern char _sextratext[] __attribute__((weak));
+extern char _eextratext[] __attribute__((weak));
 extern char _end[];
 
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 9cac8e8..8786e01 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -236,11 +236,18 @@
 #define SIGEV_THREAD	2	/* deliver via thread creation */
 #define SIGEV_THREAD_ID 4	/* deliver to thread */
 
-#define SIGEV_MAX_SIZE	64
-#ifndef SIGEV_PAD_SIZE
-#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+/*
+ * This works because the alignment is ok on all current architectures
+ * but we leave open this being overridden in the future
+ */
+#ifndef __ARCH_SIGEV_PREAMBLE_SIZE
+#define __ARCH_SIGEV_PREAMBLE_SIZE	(sizeof(int) * 2 + sizeof(sigval_t))
 #endif
 
+#define SIGEV_MAX_SIZE	64
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE) \
+		/ sizeof(int))
+
 typedef struct sigevent {
 	sigval_t sigev_value;
 	int sigev_signo;
diff --git a/include/asm-generic/signal.h b/include/asm-generic/signal.h
new file mode 100644
index 0000000..9418d6e
--- /dev/null
+++ b/include/asm-generic/signal.h
@@ -0,0 +1,21 @@
+#ifndef SIG_BLOCK
+#define SIG_BLOCK          0	/* for blocking signals */
+#endif
+#ifndef SIG_UNBLOCK
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#endif
+#ifndef SIG_SETMASK
+#define SIG_SETMASK        2	/* for setting the signal mask */
+#endif
+
+#ifndef __ASSEMBLY__
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
+
+typedef void __restorefn_t(void);
+typedef __restorefn_t __user *__sigrestore_t;
+
+#define SIG_DFL	((__force __sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__force __sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__force __sighandler_t)-1)	/* error return from signal */
+#endif
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index c856a43e..6c90f0f 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -76,46 +76,47 @@
 	ptr->x = val;
 }
 
-static inline unsigned long __get_unaligned(const void *ptr, size_t size)
-{
-	unsigned long val;
-	switch (size) {
-	case 1:
-		val = *(const __u8 *)ptr;
-		break;
-	case 2:
-		val = __uldw((const __u16 *)ptr);
-		break;
-	case 4:
-		val = __uldl((const __u32 *)ptr);
-		break;
-	case 8:
-		val = __uldq((const __u64 *)ptr);
-		break;
-	default:
-		bad_unaligned_access_length();
-	};
-	return val;
-}
+#define __get_unaligned(ptr, size) ({		\
+	const void *__gu_p = ptr;		\
+	unsigned long val;			\
+	switch (size) {				\
+	case 1:					\
+		val = *(const __u8 *)__gu_p;	\
+		break;				\
+	case 2:					\
+		val = __uldw(__gu_p);		\
+		break;				\
+	case 4:					\
+		val = __uldl(__gu_p);		\
+		break;				\
+	case 8:					\
+		val = __uldq(__gu_p);		\
+		break;				\
+	default:				\
+		bad_unaligned_access_length();	\
+	};					\
+	val;					\
+})
 
-static inline void __put_unaligned(unsigned long val, void *ptr, size_t size)
-{
-	switch (size) {
-	case 1:
-		*(__u8 *)ptr = val;
-	        break;
-	case 2:
-		__ustw(val, (__u16 *)ptr);
-		break;
-	case 4:
-		__ustl(val, (__u32 *)ptr);
-		break;
-	case 8:
-		__ustq(val, (__u64 *)ptr);
-		break;
-	default:
-	    	bad_unaligned_access_length();
-	};
-}
+#define __put_unaligned(val, ptr, size)		\
+do {						\
+	void *__gu_p = ptr;			\
+	switch (size) {				\
+	case 1:					\
+		*(__u8 *)__gu_p = val;		\
+	        break;				\
+	case 2:					\
+		__ustw(val, __gu_p);		\
+		break;				\
+	case 4:					\
+		__ustl(val, __gu_p);		\
+		break;				\
+	case 8:					\
+		__ustq(val, __gu_p);		\
+		break;				\
+	default:				\
+	    	bad_unaligned_access_length();	\
+	};					\
+} while(0)
 
 #endif /* _ASM_GENERIC_UNALIGNED_H */
diff --git a/include/asm-h8300/signal.h b/include/asm-h8300/signal.h
index 3a08544..8eccdc1 100644
--- a/include/asm-h8300/signal.h
+++ b/include/asm-h8300/signal.h
@@ -107,29 +107,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index e1de674..a5810cf 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -109,7 +109,6 @@
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 
-extern int check_nmi_watchdog (void);
 extern void enable_NMI_through_LVT0 (void * dummy);
 
 extern unsigned int nmi_watchdog;
diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h
index 706eb51..8f79de1 100644
--- a/include/asm-i386/bug.h
+++ b/include/asm-i386/bug.h
@@ -9,6 +9,8 @@
  * undefined" opcode for parsing in the trap handler.
  */
 
+#ifdef CONFIG_BUG
+#define HAVE_ARCH_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #define BUG()				\
  __asm__ __volatile__(	"ud2\n"		\
@@ -18,8 +20,7 @@
 #else
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
+#endif
 
-#define HAVE_ARCH_BUG
 #include <asm-generic/bug.h>
-
 #endif
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index d76a5f0..6413420 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -33,7 +33,7 @@
  *	passed in an incorrect kernel address to one of these functions.
  *
  *	If you use these functions directly please don't forget the
- *	verify_area().
+ *	access_ok().
  */
 static __inline__
 unsigned int csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst,
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index e147cab..ff1187e 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -87,8 +87,8 @@
 #define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
 
 /* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM	(5*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY	(5*32+ 1) /* If yes HyperThreading not valid */
+#define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
 
 #define cpu_has(c, bit)		test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)	test_bit(bit, boot_cpu_data.x86_capability)
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index 5c285ae..edf65be 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -13,7 +13,7 @@
 #define __E820_HEADER
 
 #define E820MAP	0x2d0		/* our map */
-#define E820MAX	32		/* number of entries in E820MAP */
+#define E820MAX	128		/* number of entries in E820MAP */
 #define E820NR	0x1e8		/* # entries in E820MAP */
 
 #define E820_RAM	1
diff --git a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h
index f478228..79727af 100644
--- a/include/asm-i386/floppy.h
+++ b/include/asm-i386/floppy.h
@@ -257,7 +257,7 @@
 	return 0;
 }
 
-struct fd_routine_l {
+static struct fd_routine_l {
 	int (*_request_dma)(unsigned int dmanr, const char * device_id);
 	void (*_free_dma)(unsigned int dmanr);
 	int (*_get_dma_residue)(unsigned int dummy);
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 6e20b07..16ef9f9 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -92,6 +92,7 @@
 
 extern unsigned long hpet_tick;  	/* hpet clks count per tick */
 extern unsigned long hpet_address;	/* hpet memory map physical address */
+extern int hpet_use_timer;
 
 extern int hpet_rtc_timer_init(void);
 extern int hpet_enable(void);
diff --git a/include/asm-i386/module.h b/include/asm-i386/module.h
index 508865e..eb7f2b4 100644
--- a/include/asm-i386/module.h
+++ b/include/asm-i386/module.h
@@ -52,8 +52,8 @@
 #define MODULE_PROC_FAMILY "CYRIXIII "
 #elif defined CONFIG_MVIAC3_2
 #define MODULE_PROC_FAMILY "VIAC3-2 "
-#elif CONFIG_MGEODE
-#define MODULE_PROC_FAMILY "GEODE "
+#elif CONFIG_MGEODEGX1
+#define MODULE_PROC_FAMILY "GEODEGX1 "
 #else
 #error unknown processor family
 #endif
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 5c72542..8d60c2b 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -193,9 +193,9 @@
 /*
  * Define this if things work differently on an i386 and an i486:
  * it will (on an i486) warn about kernel memory accesses that are
- * done without a 'verify_area(VERIFY_WRITE,..)'
+ * done without a 'access_ok(VERIFY_WRITE,..)'
  */
-#undef TEST_VERIFY_AREA
+#undef TEST_ACCESS_OK
 
 /* The boot page tables (all created as a single array) */
 extern unsigned long pg0[];
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 8814b54..7a32184 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -16,7 +16,7 @@
 #define MAXMEM_PFN	PFN_DOWN(MAXMEM)
 #define MAX_NONPAE_PFN	(1 << 20)
 
-#define PARAM_SIZE 2048
+#define PARAM_SIZE 4096
 #define COMMAND_LINE_SIZE 256
 
 #define OLD_CL_MAGIC_ADDR	0x90020
diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h
index 7ef343b..cbb47d3 100644
--- a/include/asm-i386/signal.h
+++ b/include/asm-i386/signal.h
@@ -110,34 +110,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index 1679983..6a78ac5 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -198,46 +198,79 @@
 int d0, d1, d2;
 __asm__ __volatile__(
 	"rep ; movsl\n\t"
-	"testb $2,%b4\n\t"
-	"je 1f\n\t"
-	"movsw\n"
-	"1:\ttestb $1,%b4\n\t"
-	"je 2f\n\t"
-	"movsb\n"
-	"2:"
+	"movl %4,%%ecx\n\t"
+	"andl $3,%%ecx\n\t"
+#if 1	/* want to pay 2 byte penalty for a chance to skip microcoded rep? */
+	"jz 1f\n\t"
+#endif
+	"rep ; movsb\n\t"
+	"1:"
 	: "=&c" (d0), "=&D" (d1), "=&S" (d2)
-	:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
+	: "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from)
 	: "memory");
 return (to);
 }
 
 /*
- * This looks horribly ugly, but the compiler can optimize it totally,
+ * This looks ugly, but the compiler can optimize it totally,
  * as the count is constant.
  */
 static inline void * __constant_memcpy(void * to, const void * from, size_t n)
 {
-	if (n <= 128)
-		return __builtin_memcpy(to, from, n);
-
-#define COMMON(x) \
-__asm__ __volatile__( \
-	"rep ; movsl" \
-	x \
-	: "=&c" (d0), "=&D" (d1), "=&S" (d2) \
-	: "0" (n/4),"1" ((long) to),"2" ((long) from) \
-	: "memory");
-{
-	int d0, d1, d2;
-	switch (n % 4) {
-		case 0: COMMON(""); return to;
-		case 1: COMMON("\n\tmovsb"); return to;
-		case 2: COMMON("\n\tmovsw"); return to;
-		default: COMMON("\n\tmovsw\n\tmovsb"); return to;
+	long esi, edi;
+	if (!n) return to;
+#if 1	/* want to do small copies with non-string ops? */
+	switch (n) {
+		case 1: *(char*)to = *(char*)from; return to;
+		case 2: *(short*)to = *(short*)from; return to;
+		case 4: *(int*)to = *(int*)from; return to;
+#if 1	/* including those doable with two moves? */
+		case 3: *(short*)to = *(short*)from;
+			*((char*)to+2) = *((char*)from+2); return to;
+		case 5: *(int*)to = *(int*)from;
+			*((char*)to+4) = *((char*)from+4); return to;
+		case 6: *(int*)to = *(int*)from;
+			*((short*)to+2) = *((short*)from+2); return to;
+		case 8: *(int*)to = *(int*)from;
+			*((int*)to+1) = *((int*)from+1); return to;
+#endif
 	}
-}
-  
-#undef COMMON
+#endif
+	esi = (long) from;
+	edi = (long) to;
+	if (n >= 5*4) {
+		/* large block: use rep prefix */
+		int ecx;
+		__asm__ __volatile__(
+			"rep ; movsl"
+			: "=&c" (ecx), "=&D" (edi), "=&S" (esi)
+			: "0" (n/4), "1" (edi),"2" (esi)
+			: "memory"
+		);
+	} else {
+		/* small block: don't clobber ecx + smaller code */
+		if (n >= 4*4) __asm__ __volatile__("movsl"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+		if (n >= 3*4) __asm__ __volatile__("movsl"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+		if (n >= 2*4) __asm__ __volatile__("movsl"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+		if (n >= 1*4) __asm__ __volatile__("movsl"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+	}
+	switch (n % 4) {
+		/* tail */
+		case 0: return to;
+		case 1: __asm__ __volatile__("movsb"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+			return to;
+		case 2: __asm__ __volatile__("movsw"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+			return to;
+		default: __asm__ __volatile__("movsw\n\tmovsb"
+			:"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
+			return to;
+	}
 }
 
 #define __HAVE_ARCH_MEMCPY
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 6f74d4c..3db717a 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -81,7 +81,7 @@
 #define loadsegment(seg,value)			\
 	asm volatile("\n"			\
 		"1:\t"				\
-		"movl %0,%%" #seg "\n"		\
+		"mov %0,%%" #seg "\n"		\
 		"2:\n"				\
 		".section .fixup,\"ax\"\n"	\
 		"3:\t"				\
@@ -93,13 +93,13 @@
 		".align 4\n\t"			\
 		".long 1b,3b\n"			\
 		".previous"			\
-		: :"m" (*(unsigned int *)&(value)))
+		: :"m" (value))
 
 /*
  * Save a segment register away
  */
 #define savesegment(seg, value) \
-	asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+	asm volatile("mov %%" #seg ",%0":"=m" (value))
 
 /*
  * Clear and set 'TS' bit respectively
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 925d54c..7232528 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -314,8 +314,8 @@
 #ifdef __KERNEL__
 
 /*
- * find_last_zero_bit - find the last zero bit in a 64 bit quantity
- * @x: The value to search
+ * Return bit number of last (most-significant) bit set.  Undefined
+ * for x==0.  Bits are numbered from 0..63 (e.g., ia64_fls(9) == 3).
  */
 static inline unsigned long
 ia64_fls (unsigned long x)
@@ -327,10 +327,23 @@
 	return exp - 0xffff;
 }
 
+/*
+ * Find the last (most significant) bit set.  Returns 0 for x==0 and
+ * bits are numbered from 1..32 (e.g., fls(9) == 4).
+ */
 static inline int
-fls (int x)
+fls (int t)
 {
-	return ia64_fls((unsigned int) x);
+	unsigned long x = t & 0xffffffffu;
+
+	if (!x)
+		return 0;
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+	return ia64_popcnt(x);
 }
 
 /*
diff --git a/include/asm-ia64/bug.h b/include/asm-ia64/bug.h
index 2c0cd51..3aa0a0a 100644
--- a/include/asm-ia64/bug.h
+++ b/include/asm-ia64/bug.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_IA64_BUG_H
 #define _ASM_IA64_BUG_H
 
+#ifdef CONFIG_BUG
 #if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
 # define ia64_abort()	__builtin_trap()
 #else
@@ -8,8 +9,10 @@
 #endif
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
 
-/* should this BUG should be made generic? */
+/* should this BUG be made generic? */
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
index 7c357df..4fb4e43 100644
--- a/include/asm-ia64/gcc_intrin.h
+++ b/include/asm-ia64/gcc_intrin.h
@@ -133,13 +133,17 @@
 	ia64_intri_res;								\
 })
 
-#define ia64_popcnt(x)						\
-({								\
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# define ia64_popcnt(x)		__builtin_popcountl(x)
+#else
+# define ia64_popcnt(x)						\
+  ({								\
 	__u64 ia64_intri_res;					\
 	asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x));	\
 								\
 	ia64_intri_res;						\
-})
+  })
+#endif
 
 #define ia64_getf_exp(x)					\
 ({								\
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index 041ab8c..cd4e06b 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -81,6 +81,7 @@
 
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
+extern int assign_irq_vector_nopanic (int irq); /* allocate a free vector without panic */
 extern int assign_irq_vector (int irq);	/* allocate a free vector */
 extern void free_irq_vector (int vector);
 extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 5dd477f..2303a10 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -67,6 +67,7 @@
 #define PAL_REGISTER_INFO	39	/* return AR and CR register information*/
 #define PAL_SHUTDOWN		40	/* enter processor shutdown state */
 #define PAL_PREFETCH_VISIBILITY	41	/* Make Processor Prefetches Visible */
+#define PAL_LOGICAL_TO_PHYSICAL 42	/* returns information on logical to physical processor mapping */
 
 #define PAL_COPY_PAL		256	/* relocate PAL procedures and PAL PMI */
 #define PAL_HALT_INFO		257	/* return the low power capabilities of processor */
@@ -1559,6 +1560,73 @@
 	return iprv.status;
 }
 
+/* data structure for getting information on logical to physical mappings */
+typedef union pal_log_overview_u {
+	struct {
+		u64	num_log		:16,	/* Total number of logical
+						 * processors on this die
+						 */
+			tpc		:8,	/* Threads per core */
+			reserved3	:8,	/* Reserved */
+			cpp		:8,	/* Cores per processor */
+			reserved2	:8,	/* Reserved */
+			ppid		:8,	/* Physical processor ID */
+			reserved1	:8;	/* Reserved */
+	} overview_bits;
+	u64 overview_data;
+} pal_log_overview_t;
+
+typedef union pal_proc_n_log_info1_u{
+	struct {
+		u64	tid		:16,	/* Thread id */
+			reserved2	:16,	/* Reserved */
+			cid		:16,	/* Core id */
+			reserved1	:16;	/* Reserved */
+	} ppli1_bits;
+	u64	ppli1_data;
+} pal_proc_n_log_info1_t;
+
+typedef union pal_proc_n_log_info2_u {
+	struct {
+		u64	la		:16,	/* Logical address */
+			reserved	:48;	/* Reserved */
+	} ppli2_bits;
+	u64	ppli2_data;
+} pal_proc_n_log_info2_t;
+
+typedef struct pal_logical_to_physical_s
+{
+	pal_log_overview_t overview;
+	pal_proc_n_log_info1_t ppli1;
+	pal_proc_n_log_info2_t ppli2;
+} pal_logical_to_physical_t;
+
+#define overview_num_log	overview.overview_bits.num_log
+#define overview_tpc		overview.overview_bits.tpc
+#define overview_cpp		overview.overview_bits.cpp
+#define overview_ppid		overview.overview_bits.ppid
+#define log1_tid		ppli1.ppli1_bits.tid
+#define log1_cid		ppli1.ppli1_bits.cid
+#define log2_la			ppli2.ppli2_bits.la
+
+/* Get information on logical to physical processor mappings. */
+static inline s64
+ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
+{
+	struct ia64_pal_retval iprv;
+
+	PAL_CALL(iprv, PAL_LOGICAL_TO_PHYSICAL, proc_number, 0, 0);
+
+	if (iprv.status == PAL_STATUS_SUCCESS)
+	{
+		if (proc_number == 0)
+			mapping->overview.overview_data = iprv.v0;
+		mapping->ppli1.ppli1_data = iprv.v1;
+		mapping->ppli2.ppli2_data = iprv.v2;
+	}
+
+	return iprv.status;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PAL_H */
diff --git a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h
index 136c60e..ed5416c 100644
--- a/include/asm-ia64/perfmon.h
+++ b/include/asm-ia64/perfmon.h
@@ -254,6 +254,18 @@
 #define PFM_CPUINFO_DCR_PP	0x2	/* if set the system wide session has started */
 #define PFM_CPUINFO_EXCL_IDLE	0x4	/* the system wide session excludes the idle task */
 
+/*
+ * sysctl control structure. visible to sampling formats
+ */
+typedef struct {
+	int	debug;		/* turn on/off debugging via syslog */
+	int	debug_ovfl;	/* turn on/off debug printk in overflow handler */
+	int	fastctxsw;	/* turn on/off fast (unsecure) ctxsw */
+	int	expert_mode;	/* turn on/off value checking */
+} pfm_sysctl_t;
+extern pfm_sysctl_t pfm_sysctl;
+
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_IA64_PERFMON_H */
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
index 0f05dc8..a5f2145 100644
--- a/include/asm-ia64/pgalloc.h
+++ b/include/asm-ia64/pgalloc.h
@@ -22,146 +22,124 @@
 
 #include <asm/mmu_context.h>
 
-/*
- * Very stupidly, we used to get new pgd's and pmd's, init their contents
- * to point to the NULL versions of the next level page table, later on
- * completely re-init them the same way, then free them up.  This wasted
- * a lot of work and caused unnecessary memory traffic.  How broken...
- * We fix this by caching them.
- */
-#define pgd_quicklist		(local_cpu_data->pgd_quick)
-#define pmd_quicklist		(local_cpu_data->pmd_quick)
-#define pgtable_cache_size	(local_cpu_data->pgtable_cache_sz)
+DECLARE_PER_CPU(unsigned long *, __pgtable_quicklist);
+#define pgtable_quicklist __ia64_per_cpu_var(__pgtable_quicklist)
+DECLARE_PER_CPU(long, __pgtable_quicklist_size);
+#define pgtable_quicklist_size __ia64_per_cpu_var(__pgtable_quicklist_size)
 
-static inline pgd_t*
-pgd_alloc_one_fast (struct mm_struct *mm)
+static inline long pgtable_quicklist_total_size(void)
+{
+	long ql_size = 0;
+	int cpuid;
+
+	for_each_online_cpu(cpuid) {
+		ql_size += per_cpu(__pgtable_quicklist_size, cpuid);
+	}
+	return ql_size;
+}
+
+static inline void *pgtable_quicklist_alloc(void)
 {
 	unsigned long *ret = NULL;
 
 	preempt_disable();
 
-	ret = pgd_quicklist;
+	ret = pgtable_quicklist;
 	if (likely(ret != NULL)) {
-		pgd_quicklist = (unsigned long *)(*ret);
+		pgtable_quicklist = (unsigned long *)(*ret);
 		ret[0] = 0;
-		--pgtable_cache_size;
-	} else
-		ret = NULL;
-
-	preempt_enable();
-
-	return (pgd_t *) ret;
-}
-
-static inline pgd_t*
-pgd_alloc (struct mm_struct *mm)
-{
-	/* the VM system never calls pgd_alloc_one_fast(), so we do it here. */
-	pgd_t *pgd = pgd_alloc_one_fast(mm);
-
-	if (unlikely(pgd == NULL)) {
-		pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
+		--pgtable_quicklist_size;
+		preempt_enable();
+	} else {
+		preempt_enable();
+		ret = (unsigned long *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 	}
-	return pgd;
+
+	return ret;
 }
 
-static inline void
-pgd_free (pgd_t *pgd)
+static inline void pgtable_quicklist_free(void *pgtable_entry)
 {
+#ifdef CONFIG_NUMA
+	unsigned long nid = page_to_nid(virt_to_page(pgtable_entry));
+
+	if (unlikely(nid != numa_node_id())) {
+		free_page((unsigned long)pgtable_entry);
+		return;
+	}
+#endif
+
 	preempt_disable();
-	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
-	pgd_quicklist = (unsigned long *) pgd;
-	++pgtable_cache_size;
+	*(unsigned long *)pgtable_entry = (unsigned long)pgtable_quicklist;
+	pgtable_quicklist = (unsigned long *)pgtable_entry;
+	++pgtable_quicklist_size;
 	preempt_enable();
 }
 
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return pgtable_quicklist_alloc();
+}
+
+static inline void pgd_free(pgd_t * pgd)
+{
+	pgtable_quicklist_free(pgd);
+}
+
 static inline void
-pud_populate (struct mm_struct *mm, pud_t *pud_entry, pmd_t *pmd)
+pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd)
 {
 	pud_val(*pud_entry) = __pa(pmd);
 }
 
-static inline pmd_t*
-pmd_alloc_one_fast (struct mm_struct *mm, unsigned long addr)
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	unsigned long *ret = NULL;
-
-	preempt_disable();
-
-	ret = (unsigned long *)pmd_quicklist;
-	if (likely(ret != NULL)) {
-		pmd_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		--pgtable_cache_size;
-	}
-
-	preempt_enable();
-
-	return (pmd_t *)ret;
+	return pgtable_quicklist_alloc();
 }
 
-static inline pmd_t*
-pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
+static inline void pmd_free(pmd_t * pmd)
 {
-	pmd_t *pmd = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
-
-	return pmd;
-}
-
-static inline void
-pmd_free (pmd_t *pmd)
-{
-	preempt_disable();
-	*(unsigned long *)pmd = (unsigned long) pmd_quicklist;
-	pmd_quicklist = (unsigned long *) pmd;
-	++pgtable_cache_size;
-	preempt_enable();
+	pgtable_quicklist_free(pmd);
 }
 
 #define __pmd_free_tlb(tlb, pmd)	pmd_free(pmd)
 
 static inline void
-pmd_populate (struct mm_struct *mm, pmd_t *pmd_entry, struct page *pte)
+pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte)
 {
 	pmd_val(*pmd_entry) = page_to_phys(pte);
 }
 
 static inline void
-pmd_populate_kernel (struct mm_struct *mm, pmd_t *pmd_entry, pte_t *pte)
+pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte)
 {
 	pmd_val(*pmd_entry) = __pa(pte);
 }
 
-static inline struct page *
-pte_alloc_one (struct mm_struct *mm, unsigned long addr)
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+					 unsigned long addr)
 {
-	struct page *pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
-
-	return pte;
+	return virt_to_page(pgtable_quicklist_alloc());
 }
 
-static inline pte_t *
-pte_alloc_one_kernel (struct mm_struct *mm, unsigned long addr)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long addr)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
-
-	return pte;
+	return pgtable_quicklist_alloc();
 }
 
-static inline void
-pte_free (struct page *pte)
+static inline void pte_free(struct page *pte)
 {
-	__free_page(pte);
+	pgtable_quicklist_free(page_address(pte));
 }
 
-static inline void
-pte_free_kernel (pte_t *pte)
+static inline void pte_free_kernel(pte_t * pte)
 {
-	free_page((unsigned long) pte);
+	pgtable_quicklist_free(pte);
 }
 
-#define __pte_free_tlb(tlb, pte)	tlb_remove_page((tlb), (pte))
+#define __pte_free_tlb(tlb, pte)	pte_free(pte)
 
-extern void check_pgt_cache (void);
+extern void check_pgt_cache(void);
 
-#endif /* _ASM_IA64_PGALLOC_H */
+#endif				/* _ASM_IA64_PGALLOC_H */
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 2807f8d..9e1ba8b 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -137,9 +137,6 @@
 	__u64 nsec_per_cyc;	/* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
 	__u64 unimpl_va_mask;	/* mask of unimplemented virtual address bits (from PAL) */
 	__u64 unimpl_pa_mask;	/* mask of unimplemented physical address bits (from PAL) */
-	__u64 *pgd_quick;
-	__u64 *pmd_quick;
-	__u64 pgtable_cache_sz;
 	__u64 itc_freq;		/* frequency of ITC counter */
 	__u64 proc_freq;	/* frequency of processor */
 	__u64 cyc_per_usec;	/* itc_freq/1000000 */
@@ -151,6 +148,13 @@
 #ifdef CONFIG_SMP
 	__u64 loops_per_jiffy;
 	int cpu;
+	__u32 socket_id;	/* physical processor socket id */
+	__u16 core_id;		/* core id */
+	__u16 thread_id;	/* thread id */
+	__u16 num_log;		/* Total number of logical processors on
+				 * this socket that were successfully booted */
+	__u8  cores_per_socket;	/* Cores per processor socket */
+	__u8  threads_per_core;	/* Threads per core */
 #endif
 
 	/* CPUID-derived information: */
diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
index ea1ed37..29df88b 100644
--- a/include/asm-ia64/sal.h
+++ b/include/asm-ia64/sal.h
@@ -91,6 +91,7 @@
 #define SAL_PCI_CONFIG_READ		0x01000010
 #define SAL_PCI_CONFIG_WRITE		0x01000011
 #define SAL_FREQ_BASE			0x01000012
+#define SAL_PHYSICAL_ID_INFO		0x01000013
 
 #define SAL_UPDATE_PAL			0x01000020
 
@@ -815,6 +816,17 @@
 	return isrv.status;
 }
 
+/* Get physical processor die mapping in the platform. */
+static inline s64
+ia64_sal_physical_id_info(u16 *splid)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_PHYSICAL_ID_INFO, 0, 0, 0, 0, 0, 0, 0);
+	if (splid)
+		*splid = isrv.v0;
+	return isrv.status;
+}
+
 extern unsigned long sal_platform_features;
 
 extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
@@ -832,6 +844,44 @@
 				   u64, u64, u64, u64, u64);
 extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
 				      u64, u64, u64, u64, u64);
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * System Abstraction Layer Specification
+ * Section 3.2.5.1: OS_BOOT_RENDEZ to SAL return State.
+ * Note: region regs are stored first in head.S _start. Hence they must
+ * stay up front.
+ */
+struct sal_to_os_boot {
+	u64 rr[8];		/* Region Registers */
+	u64	br[6];		/* br0: return addr into SAL boot rendez routine */
+	u64 gr1;		/* SAL:GP */
+	u64 gr12;		/* SAL:SP */
+	u64 gr13;		/* SAL: Task Pointer */
+	u64 fpsr;
+	u64	pfs;
+	u64 rnat;
+	u64 unat;
+	u64 bspstore;
+	u64 dcr;		/* Default Control Register */
+	u64 iva;
+	u64 pta;
+	u64 itv;
+	u64 pmv;
+	u64 cmcv;
+	u64 lrr[2];
+	u64 gr[4];
+	u64 pr;			/* Predicate registers */
+	u64 lc;			/* Loop Count */
+	struct ia64_fpreg fp[20];
+};
+
+/*
+ * Global array allocated for NR_CPUS at boot time
+ */
+extern struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
+
+extern void ia64_jump_to_sal(struct sal_to_os_boot *);
+#endif
 
 extern void ia64_sal_handler_init(void *entry_point, void *gpval);
 
diff --git a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
index d55f139..9294e4b 100644
--- a/include/asm-ia64/siginfo.h
+++ b/include/asm-ia64/siginfo.h
@@ -8,9 +8,7 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
-#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 4)
-
-#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 4)
+#define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
 
 #define HAVE_ARCH_SIGINFO_T
 #define HAVE_ARCH_COPY_SIGINFO
diff --git a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h
index 660a759..608168d 100644
--- a/include/asm-ia64/signal.h
+++ b/include/asm-ia64/signal.h
@@ -114,27 +114,11 @@
 #define _NSIG_BPW	64
 #define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
 
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
 #define SA_PERCPU_IRQ		0x02000000
 
 #endif /* __KERNEL__ */
 
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 # ifndef __ASSEMBLY__
 
@@ -143,9 +127,6 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;
 
-/* Type of a signal handler.  */
-typedef void __user (*__sighandler_t)(int);
-
 typedef struct sigaltstack {
 	void __user *ss_sp;
 	int ss_flags;
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index c4a227a..3ba1a06 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -56,6 +56,10 @@
 extern char no_int_routing __devinitdata;
 
 extern cpumask_t cpu_online_map;
+extern cpumask_t cpu_core_map[NR_CPUS];
+extern cpumask_t cpu_sibling_map[NR_CPUS];
+extern int smp_num_siblings;
+extern int smp_num_cpucores;
 extern void __iomem *ipi_base_addr;
 extern unsigned char smp_int_redirect;
 
@@ -124,6 +128,7 @@
 extern void smp_send_reschedule (int cpu);
 extern void lock_ipi_calllock(void);
 extern void unlock_ipi_calllock(void);
+extern void identify_siblings (struct cpuinfo_ia64 *);
 
 #else
 
diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h
index c916bd2..1bfdfb4 100644
--- a/include/asm-ia64/sn/addrs.h
+++ b/include/asm-ia64/sn/addrs.h
@@ -136,6 +136,7 @@
  */
 #define CAC_BASE		(CACHED   | AS_CAC_SPACE)
 #define AMO_BASE		(UNCACHED | AS_AMO_SPACE)
+#define AMO_PHYS_BASE		(UNCACHED_PHYS | AS_AMO_SPACE)
 #define GET_BASE		(CACHED   | AS_GET_SPACE)
 
 /*
@@ -154,12 +155,20 @@
  *           the chiplet id is zero.  If we implement TIO-TIO dma, we might need
  *           to insert a chiplet id into this macro.  However, it is our belief
  *           right now that this chiplet id will be ICE, which is also zero.
+ *           Nasid starts on bit 40.
  */
-#define PHYS_TO_TIODMA(x)	( (((u64)(x) & NASID_MASK) << 2) | NODE_OFFSET(x))
+#define PHYS_TO_TIODMA(x)	( (((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x))
 #define PHYS_TO_DMA(x)          ( (((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x))
 
 
 /*
+ * Macros to test for address type.
+ */
+#define IS_AMO_ADDRESS(x)	(((u64)(x) & (REGION_BITS | AS_MASK)) == AMO_BASE)
+#define IS_AMO_PHYS_ADDRESS(x)	(((u64)(x) & (REGION_BITS | AS_MASK)) == AMO_PHYS_BASE)
+
+
+/*
  * The following definitions pertain to the IO special address
  * space.  They define the location of the big and little windows
  * of any given node.
@@ -168,7 +177,10 @@
 #define TIO_BWIN_SIZE_BITS		30	/* big window size: 1G */
 #define NODE_SWIN_BASE(n, w)		((w == 0) ? NODE_BWIN_BASE((n), SWIN0_BIGWIN) \
 		: RAW_NODE_SWIN_BASE(n, w))
+#define TIO_SWIN_BASE(n, w) 		(TIO_IO_BASE(n) + \
+					    ((u64) (w) << TIO_SWIN_SIZE_BITS))
 #define NODE_IO_BASE(n)			(GLOBAL_MMR_SPACE | NASID_SPACE(n))
+#define TIO_IO_BASE(n)                  (UNCACHED | NASID_SPACE(n))
 #define BWIN_SIZE			(1UL << BWIN_SIZE_BITS)
 #define NODE_BWIN_BASE0(n)		(NODE_IO_BASE(n) + BWIN_SIZE)
 #define NODE_BWIN_BASE(n, w)		(NODE_BWIN_BASE0(n) + ((u64) (w) << BWIN_SIZE_BITS))
diff --git a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h
index 7c349f0..635fdce 100644
--- a/include/asm-ia64/sn/arch.h
+++ b/include/asm-ia64/sn/arch.h
@@ -5,7 +5,7 @@
  *
  * SGI specific setup.
  *
- * Copyright (C) 1995-1997,1999,2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (C) 1995-1997,1999,2001-2005 Silicon Graphics, Inc.  All rights reserved.
  * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
  */
 #ifndef _ASM_IA64_SN_ARCH_H
@@ -47,6 +47,21 @@
 #define MAX_COMPACT_NODES	2048
 #define CPUS_PER_NODE		4
 
+
+/*
+ * Compact node ID to nasid mappings kept in the per-cpu data areas of each
+ * cpu.
+ */
+DECLARE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]);
+#define sn_cnodeid_to_nasid	(&__get_cpu_var(__sn_cnodeid_to_nasid[0]))
+
+
+
+extern u8 sn_partition_id;
+extern u8 sn_system_size;
+extern u8 sn_sharing_domain_size;
+extern u8 sn_region_size;
+
 extern void sn_flush_all_caches(long addr, long bytes);
 
 #endif /* _ASM_IA64_SN_ARCH_H */
diff --git a/include/asm-ia64/sn/bte.h b/include/asm-ia64/sn/bte.h
index 0ec27f9..f50da3d 100644
--- a/include/asm-ia64/sn/bte.h
+++ b/include/asm-ia64/sn/bte.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 
@@ -13,8 +13,12 @@
 #include <linux/timer.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
+#include <asm/sn/pda.h>
 #include <asm/sn/types.h>
+#include <asm/sn/shub_mmr.h>
 
+#define IBCT_NOTIFY             (0x1UL << 4)
+#define IBCT_ZFIL_MODE          (0x1UL << 0)
 
 /* #define BTE_DEBUG */
 /* #define BTE_DEBUG_VERBOSE */
@@ -39,8 +43,36 @@
 
 
 /* Define hardware */
-#define BTES_PER_NODE 2
+#define BTES_PER_NODE (is_shub2() ? 4 : 2)
+#define MAX_BTES_PER_NODE 4
 
+#define BTE2OFF_CTRL	(0)
+#define BTE2OFF_SRC	(SH2_BT_ENG_SRC_ADDR_0 - SH2_BT_ENG_CSR_0)
+#define BTE2OFF_DEST	(SH2_BT_ENG_DEST_ADDR_0 - SH2_BT_ENG_CSR_0)
+#define BTE2OFF_NOTIFY	(SH2_BT_ENG_NOTIF_ADDR_0 - SH2_BT_ENG_CSR_0)
+
+#define BTE_BASE_ADDR(interface) 				\
+    (is_shub2() ? (interface == 0) ? SH2_BT_ENG_CSR_0 :		\
+		  (interface == 1) ? SH2_BT_ENG_CSR_1 :		\
+		  (interface == 2) ? SH2_BT_ENG_CSR_2 :		\
+		  		     SH2_BT_ENG_CSR_3 		\
+		: (interface == 0) ? IIO_IBLS0 : IIO_IBLS1)
+
+#define BTE_SOURCE_ADDR(base)					\
+    (is_shub2() ? base + (BTE2OFF_SRC/8) 			\
+		: base + (BTEOFF_SRC/8))
+
+#define BTE_DEST_ADDR(base)					\
+    (is_shub2() ? base + (BTE2OFF_DEST/8) 			\
+		: base + (BTEOFF_DEST/8))
+
+#define BTE_CTRL_ADDR(base)					\
+    (is_shub2() ? base + (BTE2OFF_CTRL/8) 			\
+		: base + (BTEOFF_CTRL/8))
+
+#define BTE_NOTIF_ADDR(base)					\
+    (is_shub2() ? base + (BTE2OFF_NOTIFY/8) 			\
+		: base + (BTEOFF_NOTIFY/8))
 
 /* Define hardware modes */
 #define BTE_NOTIFY (IBCT_NOTIFY)
@@ -68,14 +100,18 @@
 #define BTE_LNSTAT_STORE(_bte, _x)					\
 			HUB_S(_bte->bte_base_addr, (_x))
 #define BTE_SRC_STORE(_bte, _x)						\
-			HUB_S(_bte->bte_base_addr + (BTEOFF_SRC/8), (_x))
+			HUB_S(_bte->bte_source_addr, (_x))
 #define BTE_DEST_STORE(_bte, _x)					\
-			HUB_S(_bte->bte_base_addr + (BTEOFF_DEST/8), (_x))
+			HUB_S(_bte->bte_destination_addr, (_x))
 #define BTE_CTRL_STORE(_bte, _x)					\
-			HUB_S(_bte->bte_base_addr + (BTEOFF_CTRL/8), (_x))
+			HUB_S(_bte->bte_control_addr, (_x))
 #define BTE_NOTIF_STORE(_bte, _x)					\
-			HUB_S(_bte->bte_base_addr + (BTEOFF_NOTIFY/8), (_x))
+			HUB_S(_bte->bte_notify_addr, (_x))
 
+#define BTE_START_TRANSFER(_bte, _len, _mode)				\
+	is_shub2() ? BTE_CTRL_STORE(_bte, IBLS_BUSY | (_mode << 24) | _len) \
+		: BTE_LNSTAT_STORE(_bte, _len);				\
+		  BTE_CTRL_STORE(_bte, _mode)
 
 /* Possible results from bte_copy and bte_unaligned_copy */
 /* The following error codes map into the BTE hardware codes
@@ -110,6 +146,10 @@
 struct bteinfo_s {
 	volatile u64 notify ____cacheline_aligned;
 	u64 *bte_base_addr ____cacheline_aligned;
+	u64 *bte_source_addr;
+	u64 *bte_destination_addr;
+	u64 *bte_control_addr;
+	u64 *bte_notify_addr;
 	spinlock_t spinlock;
 	cnodeid_t bte_cnode;	/* cnode                            */
 	int bte_error_count;	/* Number of errors encountered     */
@@ -117,6 +157,7 @@
 	int cleanup_active;	/* Interface is locked for cleanup  */
 	volatile bte_result_t bh_error;	/* error while processing   */
 	volatile u64 *most_rcnt_na;
+	struct bteinfo_s *btes_to_try[MAX_BTES_PER_NODE];
 };
 
 
diff --git a/include/asm-ia64/sn/fetchop.h b/include/asm-ia64/sn/fetchop.h
deleted file mode 100644
index 5f4ad8f..0000000
--- a/include/asm-ia64/sn/fetchop.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
- */
-
-#ifndef _ASM_IA64_SN_FETCHOP_H
-#define _ASM_IA64_SN_FETCHOP_H
-
-#include <linux/config.h>
-
-#define FETCHOP_BASENAME	"sgi_fetchop"
-#define FETCHOP_FULLNAME	"/dev/sgi_fetchop"
-
-
-
-#define FETCHOP_VAR_SIZE 64 /* 64 byte per fetchop variable */
-
-#define FETCHOP_LOAD		0
-#define FETCHOP_INCREMENT	8
-#define FETCHOP_DECREMENT	16
-#define FETCHOP_CLEAR		24
-
-#define FETCHOP_STORE		0
-#define FETCHOP_AND		24
-#define FETCHOP_OR		32
-
-#define FETCHOP_CLEAR_CACHE	56
-
-#define FETCHOP_LOAD_OP(addr, op) ( \
-         *(volatile long *)((char*) (addr) + (op)))
-
-#define FETCHOP_STORE_OP(addr, op, x) ( \
-         *(volatile long *)((char*) (addr) + (op)) = (long) (x))
-
-#ifdef __KERNEL__
-
-/*
- * Convert a region 6 (kaddr) address to the address of the fetchop variable
- */
-#define FETCHOP_KADDR_TO_MSPEC_ADDR(kaddr)	TO_MSPEC(kaddr)
-
-
-/*
- * Each Atomic Memory Operation (AMO formerly known as fetchop)
- * variable is 64 bytes long.  The first 8 bytes are used.  The
- * remaining 56 bytes are unaddressable due to the operation taking
- * that portion of the address.
- * 
- * NOTE: The AMO_t _MUST_ be placed in either the first or second half
- * of the cache line.  The cache line _MUST NOT_ be used for anything
- * other than additional AMO_t entries.  This is because there are two
- * addresses which reference the same physical cache line.  One will
- * be a cached entry with the memory type bits all set.  This address
- * may be loaded into processor cache.  The AMO_t will be referenced
- * uncached via the memory special memory type.  If any portion of the
- * cached cache-line is modified, when that line is flushed, it will
- * overwrite the uncached value in physical memory and lead to
- * inconsistency.
- */
-typedef struct {
-        u64 variable;
-        u64 unused[7];
-} AMO_t;
-
-
-/*
- * The following APIs are externalized to the kernel to allocate/free pages of
- * fetchop variables.
- *	fetchop_kalloc_page	- Allocate/initialize 1 fetchop page on the
- *				  specified cnode. 
- *	fetchop_kfree_page	- Free a previously allocated fetchop page
- */
-
-unsigned long fetchop_kalloc_page(int nid);
-void fetchop_kfree_page(unsigned long maddr);
-
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_IA64_SN_FETCHOP_H */
-
diff --git a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h
index f566343..84b2546 100644
--- a/include/asm-ia64/sn/geo.h
+++ b/include/asm-ia64/sn/geo.h
@@ -18,32 +18,34 @@
 #define GEOID_SIZE	8	/* Would 16 be better?  The size can
 				   be different on different platforms. */
 
-#define MAX_SLABS	0xe	/* slabs per module */
+#define MAX_SLOTS	0xf	/* slots per module */
+#define MAX_SLABS	0xf	/* slabs per slot */
 
 typedef unsigned char	geo_type_t;
 
 /* Fields common to all substructures */
-typedef struct geo_any_s {
+typedef struct geo_common_s {
     moduleid_t	module;		/* The module (box) this h/w lives in */
     geo_type_t	type;		/* What type of h/w is named by this geoid_t */
-    slabid_t	slab;		/* The logical assembly within the module */
-} geo_any_t;
+    slabid_t	slab:4;		/* slab (ASIC), 0 .. 15 within slot */
+    slotid_t	slot:4;		/* slot (Blade), 0 .. 15 within module */
+} geo_common_t;
 
 /* Additional fields for particular types of hardware */
 typedef struct geo_node_s {
-    geo_any_t	any;		/* No additional fields needed */
+    geo_common_t	common;		/* No additional fields needed */
 } geo_node_t;
 
 typedef struct geo_rtr_s {
-    geo_any_t	any;		/* No additional fields needed */
+    geo_common_t	common;		/* No additional fields needed */
 } geo_rtr_t;
 
 typedef struct geo_iocntl_s {
-    geo_any_t	any;		/* No additional fields needed */
+    geo_common_t	common;		/* No additional fields needed */
 } geo_iocntl_t;
 
 typedef struct geo_pcicard_s {
-    geo_iocntl_t	any;
+    geo_iocntl_t	common;
     char		bus;	/* Bus/widget number */
     char		slot;	/* PCI slot number */
 } geo_pcicard_t;
@@ -62,14 +64,14 @@
 
 
 typedef union geoid_u {
-    geo_any_t	any;
-    geo_node_t	node;
+    geo_common_t	common;
+    geo_node_t		node;
     geo_iocntl_t	iocntl;
     geo_pcicard_t	pcicard;
-    geo_rtr_t	rtr;
-    geo_cpu_t	cpu;
-    geo_mem_t	mem;
-    char	padsize[GEOID_SIZE];
+    geo_rtr_t		rtr;
+    geo_cpu_t		cpu;
+    geo_mem_t		mem;
+    char		padsize[GEOID_SIZE];
 } geoid_t;
 
 
@@ -104,19 +106,26 @@
 #define INVALID_CNODEID         ((cnodeid_t)-1)
 #define INVALID_PNODEID         ((pnodeid_t)-1)
 #define INVALID_SLAB            (slabid_t)-1
+#define INVALID_SLOT            (slotid_t)-1
 #define INVALID_MODULE          ((moduleid_t)-1)
 #define INVALID_PARTID          ((partid_t)-1)
 
 static inline slabid_t geo_slab(geoid_t g)
 {
-	return (g.any.type == GEO_TYPE_INVALID) ?
-		INVALID_SLAB : g.any.slab;
+	return (g.common.type == GEO_TYPE_INVALID) ?
+		INVALID_SLAB : g.common.slab;
+}
+
+static inline slotid_t geo_slot(geoid_t g)
+{
+	return (g.common.type == GEO_TYPE_INVALID) ?
+		INVALID_SLOT : g.common.slot;
 }
 
 static inline moduleid_t geo_module(geoid_t g)
 {
-	return (g.any.type == GEO_TYPE_INVALID) ?
-		INVALID_MODULE : g.any.module;
+	return (g.common.type == GEO_TYPE_INVALID) ?
+		INVALID_MODULE : g.common.module;
 }
 
 extern geoid_t cnodeid_get_geoid(cnodeid_t cnode);
diff --git a/include/asm-ia64/sn/l1.h b/include/asm-ia64/sn/l1.h
index d5dbd55..08050d3 100644
--- a/include/asm-ia64/sn/l1.h
+++ b/include/asm-ia64/sn/l1.h
@@ -29,8 +29,9 @@
 #define L1_BRICKTYPE_CHI_CG     0x76            /* v */
 #define L1_BRICKTYPE_X          0x78            /* x */
 #define L1_BRICKTYPE_X2         0x79            /* y */
-#define L1_BRICKTYPE_SA		0x5e            /* ^ */ /* TIO bringup brick */
+#define L1_BRICKTYPE_SA		0x5e            /* ^ */
 #define L1_BRICKTYPE_PA		0x6a            /* j */
 #define L1_BRICKTYPE_IA		0x6b            /* k */
+#define L1_BRICKTYPE_ATHENA	0x2b            /* + */
 
 #endif /* _ASM_IA64_SN_L1_H */
diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h
index 2fbde33..7138b1e 100644
--- a/include/asm-ia64/sn/nodepda.h
+++ b/include/asm-ia64/sn/nodepda.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
  */
 #ifndef _ASM_IA64_SN_NODEPDA_H
 #define _ASM_IA64_SN_NODEPDA_H
@@ -13,7 +13,6 @@
 #include <asm/irq.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/intr.h>
-#include <asm/sn/pda.h>
 #include <asm/sn/bte.h>
 
 /*
@@ -43,7 +42,7 @@
 	/*
 	 * The BTEs on this node are shared by the local cpus
 	 */
-	struct bteinfo_s	bte_if[BTES_PER_NODE];	/* Virtual Interface */
+	struct bteinfo_s	bte_if[MAX_BTES_PER_NODE];	/* Virtual Interface */
 	struct timer_list	bte_recovery_timer;
 	spinlock_t		bte_recovery_lock;
 
@@ -67,20 +66,18 @@
  * The next set of definitions provides this.
  * Routines are expected to use 
  *
- *	nodepda			-> to access node PDA for the node on which code is running
- *	subnodepda		-> to access subnode PDA for the subnode on which code is running
- *
- *	NODEPDA(cnode)		-> to access node PDA for cnodeid 
- *	SUBNODEPDA(cnode,sn)	-> to access subnode PDA for cnodeid/subnode
+ *	sn_nodepda   - to access node PDA for the node on which code is running
+ *	NODEPDA(cnodeid)   - to access node PDA for cnodeid
  */
 
-#define	nodepda		pda->p_nodepda		/* Ptr to this node's PDA */
-#define	NODEPDA(cnode)		(nodepda->pernode_pdaindr[cnode])
+DECLARE_PER_CPU(struct nodepda_s *, __sn_nodepda);
+#define sn_nodepda		(__get_cpu_var(__sn_nodepda))
+#define	NODEPDA(cnodeid)	(sn_nodepda->pernode_pdaindr[cnodeid])
 
 /*
  * Check if given a compact node id the corresponding node has all the
  * cpus disabled. 
  */
-#define is_headless_node(cnode)		(nr_cpus_node(cnode) == 0)
+#define is_headless_node(cnodeid)	(nr_cpus_node(cnodeid) == 0)
 
 #endif /* _ASM_IA64_SN_NODEPDA_H */
diff --git a/arch/ia64/sn/include/pci/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h
similarity index 73%
rename from arch/ia64/sn/include/pci/pcibus_provider_defs.h
rename to include/asm-ia64/sn/pcibus_provider_defs.h
index 0706561..04e27d5 100644
--- a/arch/ia64/sn/include/pci/pcibus_provider_defs.h
+++ b/include/asm-ia64/sn/pcibus_provider_defs.h
@@ -17,6 +17,9 @@
 #define PCIIO_ASIC_TYPE_PPB	1
 #define PCIIO_ASIC_TYPE_PIC	2
 #define PCIIO_ASIC_TYPE_TIOCP	3
+#define PCIIO_ASIC_TYPE_TIOCA	4
+
+#define PCIIO_ASIC_MAX_TYPES	5
 
 /*
  * Common pciio bus provider data.  There should be one of these as the
@@ -35,9 +38,15 @@
 };
 
 /*
- * DMA mapping flags
+ * SN pci bus indirection
  */
 
-#define SN_PCIDMA_CONSISTENT    0x0001
+struct sn_pcibus_provider {
+	dma_addr_t	(*dma_map)(struct pci_dev *, unsigned long, size_t);
+	dma_addr_t	(*dma_map_consistent)(struct pci_dev *, unsigned long, size_t);
+	void		(*dma_unmap)(struct pci_dev *, dma_addr_t, int);
+	void *		(*bus_fixup)(struct pcibus_bussoft *);
+};
 
+extern struct sn_pcibus_provider *sn_pci_provider[];
 #endif				/* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */
diff --git a/arch/ia64/sn/include/pci/pcidev.h b/include/asm-ia64/sn/pcidev.h
similarity index 91%
rename from arch/ia64/sn/include/pci/pcidev.h
rename to include/asm-ia64/sn/pcidev.h
index 81eb95d..ed4031d 100644
--- a/arch/ia64/sn/include/pci/pcidev.h
+++ b/include/asm-ia64/sn/pcidev.h
@@ -32,6 +32,9 @@
 #define SN_PCIDEV_BUSSOFT(pci_dev) \
 	(SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info)
 
+#define SN_PCIDEV_BUSPROVIDER(pci_dev) \
+	(SN_PCIDEV_INFO(pci_dev)->pdi_provider)
+
 #define PCIIO_BUS_NONE	255      /* bus 255 reserved */
 #define PCIIO_SLOT_NONE 255
 #define PCIIO_FUNC_NONE 255
@@ -46,6 +49,7 @@
 	struct pci_dev		*pdi_linux_pcidev;	/* Kernel pci_dev */
 
 	struct sn_irq_info	*pdi_sn_irq_info;
+	struct sn_pcibus_provider *pdi_provider;	/* sn pci ops */
 };
 
 extern void sn_irq_fixup(struct pci_dev *pci_dev,
diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h
index e940d36..ea5590c 100644
--- a/include/asm-ia64/sn/pda.h
+++ b/include/asm-ia64/sn/pda.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
  */
 #ifndef _ASM_IA64_SN_PDA_H
 #define _ASM_IA64_SN_PDA_H
@@ -11,7 +11,6 @@
 #include <linux/cache.h>
 #include <asm/percpu.h>
 #include <asm/system.h>
-#include <asm/sn/bte.h>
 
 
 /*
@@ -25,14 +24,6 @@
 
 typedef struct pda_s {
 
-	/* Having a pointer in the begining of PDA tends to increase
-	 * the chance of having this pointer in cache. (Yes something
-	 * else gets pushed out). Doing this reduces the number of memory
-	 * access to all nodepda variables to be one
-	 */
-	struct nodepda_s *p_nodepda;		/* Pointer to Per node PDA */
-	struct subnodepda_s *p_subnodepda;	/* Pointer to CPU  subnode PDA */
-
 	/*
 	 * Support for SN LEDs
 	 */
@@ -50,7 +41,6 @@
 
 	unsigned long	sn_soft_irr[4];
 	unsigned long	sn_in_service_ivecs[4];
-	short		cnodeid_to_nasid_table[MAX_NUMNODES];
 	int		sn_lb_int_war_ticks;
 	int		sn_last_irq;
 	int		sn_first_irq;
diff --git a/include/asm-ia64/sn/shub_mmr.h b/include/asm-ia64/sn/shub_mmr.h
index 5c2fcf1..323fa0c 100644
--- a/include/asm-ia64/sn/shub_mmr.h
+++ b/include/asm-ia64/sn/shub_mmr.h
@@ -4,7 +4,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2001-2005 Silicon Graphics, Inc.  All rights reserved.
  */
 
 #ifndef _ASM_IA64_SN_SHUB_MMR_H
@@ -129,6 +129,23 @@
 #define SH_EVENT_OCCURRED_II_INT1_SHFT           30
 #define SH_EVENT_OCCURRED_II_INT1_MASK           0x0000000040000000
 
+/*   SH2_EVENT_OCCURRED_EXTIO_INT2                                      */
+/*   Description:  Pending SHUB 2 EXT IO INT2                           */
+#define SH2_EVENT_OCCURRED_EXTIO_INT2_SHFT       33
+#define SH2_EVENT_OCCURRED_EXTIO_INT2_MASK       0x0000000200000000
+
+/*   SH2_EVENT_OCCURRED_EXTIO_INT3                                      */
+/*   Description:  Pending SHUB 2 EXT IO INT3                           */
+#define SH2_EVENT_OCCURRED_EXTIO_INT3_SHFT       34
+#define SH2_EVENT_OCCURRED_EXTIO_INT3_MASK       0x0000000400000000
+
+#define SH_ALL_INT_MASK \
+	(SH_EVENT_OCCURRED_UART_INT_MASK | SH_EVENT_OCCURRED_IPI_INT_MASK | \
+	 SH_EVENT_OCCURRED_II_INT0_MASK | SH_EVENT_OCCURRED_II_INT1_MASK | \
+	 SH_EVENT_OCCURRED_II_INT1_MASK | SH2_EVENT_OCCURRED_EXTIO_INT2_MASK | \
+	 SH2_EVENT_OCCURRED_EXTIO_INT3_MASK)
+
+
 /* ==================================================================== */
 /*                         LEDS                                         */
 /* ==================================================================== */
@@ -368,6 +385,17 @@
 #define SH_EVENT_OCCURRED_RTC3_INT_MASK          0x0000000004000000
 
 /* ==================================================================== */
+/*                       Register "SH_IPI_ACCESS"                       */
+/*                 CPU interrupt Access Permission Bits                 */
+/* ==================================================================== */
+
+#define SH1_IPI_ACCESS                           0x0000000110060480
+#define SH2_IPI_ACCESS0                          0x0000000010060c00
+#define SH2_IPI_ACCESS1                          0x0000000010060c80
+#define SH2_IPI_ACCESS2                          0x0000000010060d00
+#define SH2_IPI_ACCESS3                          0x0000000010060d80
+
+/* ==================================================================== */
 /*                        Register "SH_INT_CMPB"                        */
 /*                  RTC Compare Value for Processor B                   */
 /* ==================================================================== */
@@ -412,6 +440,19 @@
 #define SH_INT_CMPD_REAL_TIME_CMPD_SHFT          0
 #define SH_INT_CMPD_REAL_TIME_CMPD_MASK          0x007fffffffffffff
 
+/* ==================================================================== */
+/*                Register "SH_MD_DQLP_MMR_DIR_PRIVEC0"                 */
+/*                      privilege vector for acc=0                      */
+/* ==================================================================== */
+
+#define SH1_MD_DQLP_MMR_DIR_PRIVEC0              0x0000000100030300
+
+/* ==================================================================== */
+/*                Register "SH_MD_DQRP_MMR_DIR_PRIVEC0"                 */
+/*                      privilege vector for acc=0                      */
+/* ==================================================================== */
+
+#define SH1_MD_DQRP_MMR_DIR_PRIVEC0              0x0000000100050300
 
 /* ==================================================================== */
 /* Some MMRs are functionally identical (or close enough) on both SHUB1 */
@@ -438,4 +479,22 @@
 #define SH_INT_CMPC		shubmmr(SH, INT_CMPC)
 #define SH_INT_CMPD		shubmmr(SH, INT_CMPD)
 
+/* ========================================================================== */
+/*                        Register "SH2_BT_ENG_CSR_0"                         */
+/*                    Engine 0 Control and Status Register                    */
+/* ========================================================================== */
+
+#define SH2_BT_ENG_CSR_0                         0x0000000030040000
+#define SH2_BT_ENG_SRC_ADDR_0                    0x0000000030040080
+#define SH2_BT_ENG_DEST_ADDR_0                   0x0000000030040100
+#define SH2_BT_ENG_NOTIF_ADDR_0                  0x0000000030040180
+
+/* ========================================================================== */
+/*                       BTE interfaces 1-3                                   */
+/* ========================================================================== */
+
+#define SH2_BT_ENG_CSR_1                         0x0000000030050000
+#define SH2_BT_ENG_CSR_2                         0x0000000030060000
+#define SH2_BT_ENG_CSR_3                         0x0000000030070000
+
 #endif /* _ASM_IA64_SN_SHUB_MMR_H */
diff --git a/include/asm-ia64/sn/shubio.h b/include/asm-ia64/sn/shubio.h
index fbd880e..831b721 100644
--- a/include/asm-ia64/sn/shubio.h
+++ b/include/asm-ia64/sn/shubio.h
@@ -3,292 +3,287 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_IA64_SN_SHUBIO_H
 #define _ASM_IA64_SN_SHUBIO_H
 
-#define HUB_WIDGET_ID_MAX 0xf
-#define IIO_NUM_ITTES   7
-#define HUB_NUM_BIG_WINDOW      (IIO_NUM_ITTES - 1)
+#define HUB_WIDGET_ID_MAX	0xf
+#define IIO_NUM_ITTES		7
+#define HUB_NUM_BIG_WINDOW	(IIO_NUM_ITTES - 1)
 
-#define    IIO_WID                   0x00400000    /* Crosstalk Widget Identification */
-                                                   /* This register is also accessible from
-                                                    * Crosstalk at address 0x0.  */
-#define    IIO_WSTAT                 0x00400008    /* Crosstalk Widget Status */
-#define    IIO_WCR                   0x00400020    /* Crosstalk Widget Control Register */
-#define    IIO_ILAPR                 0x00400100    /* IO Local Access Protection Register */
-#define    IIO_ILAPO                 0x00400108    /* IO Local Access Protection Override */
-#define    IIO_IOWA                  0x00400110    /* IO Outbound Widget Access */
-#define    IIO_IIWA                  0x00400118    /* IO Inbound Widget Access */
-#define    IIO_IIDEM                 0x00400120    /* IO Inbound Device Error Mask */
-#define    IIO_ILCSR                 0x00400128    /* IO LLP Control and Status Register */
-#define    IIO_ILLR                  0x00400130    /* IO LLP Log Register    */
-#define    IIO_IIDSR                 0x00400138    /* IO Interrupt Destination */
+#define		IIO_WID			0x00400000	/* Crosstalk Widget Identification */
+							/* This register is also accessible from
+							 * Crosstalk at address 0x0.  */
+#define		IIO_WSTAT		0x00400008	/* Crosstalk Widget Status */
+#define		IIO_WCR			0x00400020	/* Crosstalk Widget Control Register */
+#define		IIO_ILAPR		0x00400100	/* IO Local Access Protection Register */
+#define		IIO_ILAPO		0x00400108	/* IO Local Access Protection Override */
+#define		IIO_IOWA		0x00400110	/* IO Outbound Widget Access */
+#define		IIO_IIWA		0x00400118	/* IO Inbound Widget Access */
+#define		IIO_IIDEM		0x00400120	/* IO Inbound Device Error Mask */
+#define		IIO_ILCSR		0x00400128	/* IO LLP Control and Status Register */
+#define		IIO_ILLR		0x00400130	/* IO LLP Log Register    */
+#define		IIO_IIDSR		0x00400138	/* IO Interrupt Destination */
 
-#define    IIO_IGFX0                 0x00400140    /* IO Graphics Node-Widget Map 0 */
-#define    IIO_IGFX1                 0x00400148    /* IO Graphics Node-Widget Map 1 */
+#define		IIO_IGFX0		0x00400140	/* IO Graphics Node-Widget Map 0 */
+#define		IIO_IGFX1		0x00400148	/* IO Graphics Node-Widget Map 1 */
 
-#define    IIO_ISCR0                 0x00400150    /* IO Scratch Register 0 */
-#define    IIO_ISCR1                 0x00400158    /* IO Scratch Register 1 */
+#define		IIO_ISCR0		0x00400150	/* IO Scratch Register 0 */
+#define		IIO_ISCR1		0x00400158	/* IO Scratch Register 1 */
 
-#define    IIO_ITTE1                 0x00400160    /* IO Translation Table Entry 1 */
-#define    IIO_ITTE2                 0x00400168    /* IO Translation Table Entry 2 */
-#define    IIO_ITTE3                 0x00400170    /* IO Translation Table Entry 3 */
-#define    IIO_ITTE4                 0x00400178    /* IO Translation Table Entry 4 */
-#define    IIO_ITTE5                 0x00400180    /* IO Translation Table Entry 5 */
-#define    IIO_ITTE6                 0x00400188    /* IO Translation Table Entry 6 */
-#define    IIO_ITTE7                 0x00400190    /* IO Translation Table Entry 7 */
+#define		IIO_ITTE1		0x00400160	/* IO Translation Table Entry 1 */
+#define		IIO_ITTE2		0x00400168	/* IO Translation Table Entry 2 */
+#define		IIO_ITTE3		0x00400170	/* IO Translation Table Entry 3 */
+#define		IIO_ITTE4		0x00400178	/* IO Translation Table Entry 4 */
+#define		IIO_ITTE5		0x00400180	/* IO Translation Table Entry 5 */
+#define		IIO_ITTE6		0x00400188	/* IO Translation Table Entry 6 */
+#define		IIO_ITTE7		0x00400190	/* IO Translation Table Entry 7 */
 
-#define    IIO_IPRB0                 0x00400198    /* IO PRB Entry 0         */
-#define    IIO_IPRB8                 0x004001A0    /* IO PRB Entry 8         */
-#define    IIO_IPRB9                 0x004001A8    /* IO PRB Entry 9         */
-#define    IIO_IPRBA                 0x004001B0    /* IO PRB Entry A         */
-#define    IIO_IPRBB                 0x004001B8    /* IO PRB Entry B         */
-#define    IIO_IPRBC                 0x004001C0    /* IO PRB Entry C         */
-#define    IIO_IPRBD                 0x004001C8    /* IO PRB Entry D         */
-#define    IIO_IPRBE                 0x004001D0    /* IO PRB Entry E         */
-#define    IIO_IPRBF                 0x004001D8    /* IO PRB Entry F         */
+#define		IIO_IPRB0		0x00400198	/* IO PRB Entry 0   */
+#define		IIO_IPRB8		0x004001A0	/* IO PRB Entry 8   */
+#define		IIO_IPRB9		0x004001A8	/* IO PRB Entry 9   */
+#define		IIO_IPRBA		0x004001B0	/* IO PRB Entry A   */
+#define		IIO_IPRBB		0x004001B8	/* IO PRB Entry B   */
+#define		IIO_IPRBC		0x004001C0	/* IO PRB Entry C   */
+#define		IIO_IPRBD		0x004001C8	/* IO PRB Entry D   */
+#define		IIO_IPRBE		0x004001D0	/* IO PRB Entry E   */
+#define		IIO_IPRBF		0x004001D8	/* IO PRB Entry F   */
 
-#define    IIO_IXCC                  0x004001E0    /* IO Crosstalk Credit Count Timeout */
-#define    IIO_IMEM                  0x004001E8    /* IO Miscellaneous Error Mask */
-#define    IIO_IXTT                  0x004001F0    /* IO Crosstalk Timeout Threshold */
-#define    IIO_IECLR                 0x004001F8    /* IO Error Clear Register */
-#define    IIO_IBCR                  0x00400200    /* IO BTE Control Register */
+#define		IIO_IXCC		0x004001E0	/* IO Crosstalk Credit Count Timeout */
+#define		IIO_IMEM		0x004001E8	/* IO Miscellaneous Error Mask */
+#define		IIO_IXTT		0x004001F0	/* IO Crosstalk Timeout Threshold */
+#define		IIO_IECLR		0x004001F8	/* IO Error Clear Register */
+#define		IIO_IBCR		0x00400200	/* IO BTE Control Register */
 
-#define    IIO_IXSM                  0x00400208    /* IO Crosstalk Spurious Message */
-#define    IIO_IXSS                  0x00400210    /* IO Crosstalk Spurious Sideband */
+#define		IIO_IXSM		0x00400208	/* IO Crosstalk Spurious Message */
+#define		IIO_IXSS		0x00400210	/* IO Crosstalk Spurious Sideband */
 
-#define    IIO_ILCT                  0x00400218    /* IO LLP Channel Test    */
+#define		IIO_ILCT		0x00400218	/* IO LLP Channel Test    */
 
-#define    IIO_IIEPH1                0x00400220    /* IO Incoming Error Packet Header, Part 1 */
-#define    IIO_IIEPH2                0x00400228    /* IO Incoming Error Packet Header, Part 2 */
+#define		IIO_IIEPH1 		0x00400220	/* IO Incoming Error Packet Header, Part 1 */
+#define		IIO_IIEPH2 		0x00400228	/* IO Incoming Error Packet Header, Part 2 */
 
+#define		IIO_ISLAPR 		0x00400230	/* IO SXB Local Access Protection Regster */
+#define		IIO_ISLAPO 		0x00400238	/* IO SXB Local Access Protection Override */
 
-#define    IIO_ISLAPR                0x00400230    /* IO SXB Local Access Protection Regster */
-#define    IIO_ISLAPO                0x00400238    /* IO SXB Local Access Protection Override */
+#define		IIO_IWI			0x00400240	/* IO Wrapper Interrupt Register */
+#define		IIO_IWEL		0x00400248	/* IO Wrapper Error Log Register */
+#define		IIO_IWC			0x00400250	/* IO Wrapper Control Register */
+#define		IIO_IWS			0x00400258	/* IO Wrapper Status Register */
+#define		IIO_IWEIM		0x00400260	/* IO Wrapper Error Interrupt Masking Register */
 
-#define    IIO_IWI                   0x00400240    /* IO Wrapper Interrupt Register */
-#define    IIO_IWEL                  0x00400248    /* IO Wrapper Error Log Register */
-#define    IIO_IWC                   0x00400250    /* IO Wrapper Control Register */
-#define    IIO_IWS                   0x00400258    /* IO Wrapper Status Register */
-#define    IIO_IWEIM                 0x00400260    /* IO Wrapper Error Interrupt Masking Register */
+#define		IIO_IPCA		0x00400300	/* IO PRB Counter Adjust */
 
-#define    IIO_IPCA                  0x00400300    /* IO PRB Counter Adjust */
+#define		IIO_IPRTE0_A		0x00400308	/* IO PIO Read Address Table Entry 0, Part A */
+#define		IIO_IPRTE1_A		0x00400310	/* IO PIO Read Address Table Entry 1, Part A */
+#define		IIO_IPRTE2_A		0x00400318	/* IO PIO Read Address Table Entry 2, Part A */
+#define		IIO_IPRTE3_A		0x00400320	/* IO PIO Read Address Table Entry 3, Part A */
+#define		IIO_IPRTE4_A		0x00400328	/* IO PIO Read Address Table Entry 4, Part A */
+#define		IIO_IPRTE5_A		0x00400330	/* IO PIO Read Address Table Entry 5, Part A */
+#define		IIO_IPRTE6_A		0x00400338	/* IO PIO Read Address Table Entry 6, Part A */
+#define		IIO_IPRTE7_A		0x00400340	/* IO PIO Read Address Table Entry 7, Part A */
 
-#define    IIO_IPRTE0_A              0x00400308    /* IO PIO Read Address Table Entry 0, Part A */
-#define    IIO_IPRTE1_A              0x00400310    /* IO PIO Read Address Table Entry 1, Part A */
-#define    IIO_IPRTE2_A              0x00400318    /* IO PIO Read Address Table Entry 2, Part A */
-#define    IIO_IPRTE3_A               0x00400320    /* IO PIO Read Address Table Entry 3, Part A */
-#define    IIO_IPRTE4_A               0x00400328    /* IO PIO Read Address Table Entry 4, Part A */
-#define    IIO_IPRTE5_A               0x00400330    /* IO PIO Read Address Table Entry 5, Part A */
-#define    IIO_IPRTE6_A               0x00400338    /* IO PIO Read Address Table Entry 6, Part A */
-#define    IIO_IPRTE7_A               0x00400340    /* IO PIO Read Address Table Entry 7, Part A */
+#define		IIO_IPRTE0_B		0x00400348	/* IO PIO Read Address Table Entry 0, Part B */
+#define		IIO_IPRTE1_B		0x00400350	/* IO PIO Read Address Table Entry 1, Part B */
+#define		IIO_IPRTE2_B		0x00400358	/* IO PIO Read Address Table Entry 2, Part B */
+#define		IIO_IPRTE3_B		0x00400360	/* IO PIO Read Address Table Entry 3, Part B */
+#define		IIO_IPRTE4_B		0x00400368	/* IO PIO Read Address Table Entry 4, Part B */
+#define		IIO_IPRTE5_B		0x00400370	/* IO PIO Read Address Table Entry 5, Part B */
+#define		IIO_IPRTE6_B		0x00400378	/* IO PIO Read Address Table Entry 6, Part B */
+#define		IIO_IPRTE7_B		0x00400380	/* IO PIO Read Address Table Entry 7, Part B */
 
-#define    IIO_IPRTE0_B              0x00400348    /* IO PIO Read Address Table Entry 0, Part B */
-#define    IIO_IPRTE1_B              0x00400350    /* IO PIO Read Address Table Entry 1, Part B */
-#define    IIO_IPRTE2_B              0x00400358    /* IO PIO Read Address Table Entry 2, Part B */
-#define    IIO_IPRTE3_B               0x00400360    /* IO PIO Read Address Table Entry 3, Part B */
-#define    IIO_IPRTE4_B               0x00400368    /* IO PIO Read Address Table Entry 4, Part B */
-#define    IIO_IPRTE5_B               0x00400370    /* IO PIO Read Address Table Entry 5, Part B */
-#define    IIO_IPRTE6_B               0x00400378    /* IO PIO Read Address Table Entry 6, Part B */
-#define    IIO_IPRTE7_B               0x00400380    /* IO PIO Read Address Table Entry 7, Part B */
+#define		IIO_IPDR		0x00400388	/* IO PIO Deallocation Register */
+#define		IIO_ICDR		0x00400390	/* IO CRB Entry Deallocation Register */
+#define		IIO_IFDR		0x00400398	/* IO IOQ FIFO Depth Register */
+#define		IIO_IIAP		0x004003A0	/* IO IIQ Arbitration Parameters */
+#define		IIO_ICMR		0x004003A8	/* IO CRB Management Register */
+#define		IIO_ICCR		0x004003B0	/* IO CRB Control Register */
+#define		IIO_ICTO		0x004003B8	/* IO CRB Timeout   */
+#define		IIO_ICTP		0x004003C0	/* IO CRB Timeout Prescalar */
 
-#define    IIO_IPDR                  0x00400388    /* IO PIO Deallocation Register */
-#define    IIO_ICDR                  0x00400390    /* IO CRB Entry Deallocation Register */
-#define    IIO_IFDR                  0x00400398    /* IO IOQ FIFO Depth Register */
-#define    IIO_IIAP                  0x004003A0    /* IO IIQ Arbitration Parameters */
-#define    IIO_ICMR                  0x004003A8    /* IO CRB Management Register */
-#define    IIO_ICCR                  0x004003B0    /* IO CRB Control Register */
-#define    IIO_ICTO                  0x004003B8    /* IO CRB Timeout         */
-#define    IIO_ICTP                  0x004003C0    /* IO CRB Timeout Prescalar */
+#define		IIO_ICRB0_A		0x00400400	/* IO CRB Entry 0_A */
+#define		IIO_ICRB0_B		0x00400408	/* IO CRB Entry 0_B */
+#define		IIO_ICRB0_C		0x00400410	/* IO CRB Entry 0_C */
+#define		IIO_ICRB0_D		0x00400418	/* IO CRB Entry 0_D */
+#define		IIO_ICRB0_E		0x00400420	/* IO CRB Entry 0_E */
 
-#define    IIO_ICRB0_A               0x00400400    /* IO CRB Entry 0_A       */
-#define    IIO_ICRB0_B               0x00400408    /* IO CRB Entry 0_B       */
-#define    IIO_ICRB0_C               0x00400410    /* IO CRB Entry 0_C       */
-#define    IIO_ICRB0_D               0x00400418    /* IO CRB Entry 0_D       */
-#define    IIO_ICRB0_E               0x00400420    /* IO CRB Entry 0_E       */
+#define		IIO_ICRB1_A		0x00400430	/* IO CRB Entry 1_A */
+#define		IIO_ICRB1_B		0x00400438	/* IO CRB Entry 1_B */
+#define		IIO_ICRB1_C		0x00400440	/* IO CRB Entry 1_C */
+#define		IIO_ICRB1_D		0x00400448	/* IO CRB Entry 1_D */
+#define		IIO_ICRB1_E		0x00400450	/* IO CRB Entry 1_E */
 
-#define    IIO_ICRB1_A               0x00400430    /* IO CRB Entry 1_A       */
-#define    IIO_ICRB1_B               0x00400438    /* IO CRB Entry 1_B       */
-#define    IIO_ICRB1_C               0x00400440    /* IO CRB Entry 1_C       */
-#define    IIO_ICRB1_D               0x00400448    /* IO CRB Entry 1_D       */
-#define    IIO_ICRB1_E               0x00400450    /* IO CRB Entry 1_E       */
+#define		IIO_ICRB2_A		0x00400460	/* IO CRB Entry 2_A */
+#define		IIO_ICRB2_B		0x00400468	/* IO CRB Entry 2_B */
+#define		IIO_ICRB2_C		0x00400470	/* IO CRB Entry 2_C */
+#define		IIO_ICRB2_D		0x00400478	/* IO CRB Entry 2_D */
+#define		IIO_ICRB2_E		0x00400480	/* IO CRB Entry 2_E */
 
-#define    IIO_ICRB2_A               0x00400460    /* IO CRB Entry 2_A       */
-#define    IIO_ICRB2_B               0x00400468    /* IO CRB Entry 2_B       */
-#define    IIO_ICRB2_C               0x00400470    /* IO CRB Entry 2_C       */
-#define    IIO_ICRB2_D               0x00400478    /* IO CRB Entry 2_D       */
-#define    IIO_ICRB2_E               0x00400480    /* IO CRB Entry 2_E       */
+#define		IIO_ICRB3_A		0x00400490	/* IO CRB Entry 3_A */
+#define		IIO_ICRB3_B		0x00400498	/* IO CRB Entry 3_B */
+#define		IIO_ICRB3_C		0x004004a0	/* IO CRB Entry 3_C */
+#define		IIO_ICRB3_D		0x004004a8	/* IO CRB Entry 3_D */
+#define		IIO_ICRB3_E		0x004004b0	/* IO CRB Entry 3_E */
 
-#define    IIO_ICRB3_A               0x00400490    /* IO CRB Entry 3_A       */
-#define    IIO_ICRB3_B               0x00400498    /* IO CRB Entry 3_B       */
-#define    IIO_ICRB3_C               0x004004a0    /* IO CRB Entry 3_C       */
-#define    IIO_ICRB3_D               0x004004a8    /* IO CRB Entry 3_D       */
-#define    IIO_ICRB3_E               0x004004b0    /* IO CRB Entry 3_E       */
+#define		IIO_ICRB4_A		0x004004c0	/* IO CRB Entry 4_A */
+#define		IIO_ICRB4_B		0x004004c8	/* IO CRB Entry 4_B */
+#define		IIO_ICRB4_C		0x004004d0	/* IO CRB Entry 4_C */
+#define		IIO_ICRB4_D		0x004004d8	/* IO CRB Entry 4_D */
+#define		IIO_ICRB4_E		0x004004e0	/* IO CRB Entry 4_E */
 
-#define    IIO_ICRB4_A               0x004004c0    /* IO CRB Entry 4_A       */
-#define    IIO_ICRB4_B               0x004004c8    /* IO CRB Entry 4_B       */
-#define    IIO_ICRB4_C               0x004004d0    /* IO CRB Entry 4_C       */
-#define    IIO_ICRB4_D               0x004004d8    /* IO CRB Entry 4_D       */
-#define    IIO_ICRB4_E               0x004004e0    /* IO CRB Entry 4_E       */
+#define		IIO_ICRB5_A		0x004004f0	/* IO CRB Entry 5_A */
+#define		IIO_ICRB5_B		0x004004f8	/* IO CRB Entry 5_B */
+#define		IIO_ICRB5_C		0x00400500	/* IO CRB Entry 5_C */
+#define		IIO_ICRB5_D		0x00400508	/* IO CRB Entry 5_D */
+#define		IIO_ICRB5_E		0x00400510	/* IO CRB Entry 5_E */
 
-#define    IIO_ICRB5_A               0x004004f0    /* IO CRB Entry 5_A       */
-#define    IIO_ICRB5_B               0x004004f8    /* IO CRB Entry 5_B       */
-#define    IIO_ICRB5_C               0x00400500    /* IO CRB Entry 5_C       */
-#define    IIO_ICRB5_D               0x00400508    /* IO CRB Entry 5_D       */
-#define    IIO_ICRB5_E               0x00400510    /* IO CRB Entry 5_E       */
+#define		IIO_ICRB6_A		0x00400520	/* IO CRB Entry 6_A */
+#define		IIO_ICRB6_B		0x00400528	/* IO CRB Entry 6_B */
+#define		IIO_ICRB6_C		0x00400530	/* IO CRB Entry 6_C */
+#define		IIO_ICRB6_D		0x00400538	/* IO CRB Entry 6_D */
+#define		IIO_ICRB6_E		0x00400540	/* IO CRB Entry 6_E */
 
-#define    IIO_ICRB6_A               0x00400520    /* IO CRB Entry 6_A       */
-#define    IIO_ICRB6_B               0x00400528    /* IO CRB Entry 6_B       */
-#define    IIO_ICRB6_C               0x00400530    /* IO CRB Entry 6_C       */
-#define    IIO_ICRB6_D               0x00400538    /* IO CRB Entry 6_D       */
-#define    IIO_ICRB6_E               0x00400540    /* IO CRB Entry 6_E       */
+#define		IIO_ICRB7_A		0x00400550	/* IO CRB Entry 7_A */
+#define		IIO_ICRB7_B		0x00400558	/* IO CRB Entry 7_B */
+#define		IIO_ICRB7_C		0x00400560	/* IO CRB Entry 7_C */
+#define		IIO_ICRB7_D		0x00400568	/* IO CRB Entry 7_D */
+#define		IIO_ICRB7_E		0x00400570	/* IO CRB Entry 7_E */
 
-#define    IIO_ICRB7_A               0x00400550    /* IO CRB Entry 7_A       */
-#define    IIO_ICRB7_B               0x00400558    /* IO CRB Entry 7_B       */
-#define    IIO_ICRB7_C               0x00400560    /* IO CRB Entry 7_C       */
-#define    IIO_ICRB7_D               0x00400568    /* IO CRB Entry 7_D       */
-#define    IIO_ICRB7_E               0x00400570    /* IO CRB Entry 7_E       */
+#define		IIO_ICRB8_A		0x00400580	/* IO CRB Entry 8_A */
+#define		IIO_ICRB8_B		0x00400588	/* IO CRB Entry 8_B */
+#define		IIO_ICRB8_C		0x00400590	/* IO CRB Entry 8_C */
+#define		IIO_ICRB8_D		0x00400598	/* IO CRB Entry 8_D */
+#define		IIO_ICRB8_E		0x004005a0	/* IO CRB Entry 8_E */
 
-#define    IIO_ICRB8_A               0x00400580    /* IO CRB Entry 8_A       */
-#define    IIO_ICRB8_B               0x00400588    /* IO CRB Entry 8_B       */
-#define    IIO_ICRB8_C               0x00400590    /* IO CRB Entry 8_C       */
-#define    IIO_ICRB8_D               0x00400598    /* IO CRB Entry 8_D       */
-#define    IIO_ICRB8_E               0x004005a0    /* IO CRB Entry 8_E       */
+#define		IIO_ICRB9_A		0x004005b0	/* IO CRB Entry 9_A */
+#define		IIO_ICRB9_B		0x004005b8	/* IO CRB Entry 9_B */
+#define		IIO_ICRB9_C		0x004005c0	/* IO CRB Entry 9_C */
+#define		IIO_ICRB9_D		0x004005c8	/* IO CRB Entry 9_D */
+#define		IIO_ICRB9_E		0x004005d0	/* IO CRB Entry 9_E */
 
-#define    IIO_ICRB9_A               0x004005b0    /* IO CRB Entry 9_A       */
-#define    IIO_ICRB9_B               0x004005b8    /* IO CRB Entry 9_B       */
-#define    IIO_ICRB9_C               0x004005c0    /* IO CRB Entry 9_C       */
-#define    IIO_ICRB9_D               0x004005c8    /* IO CRB Entry 9_D       */
-#define    IIO_ICRB9_E               0x004005d0    /* IO CRB Entry 9_E       */
+#define		IIO_ICRBA_A		0x004005e0	/* IO CRB Entry A_A */
+#define		IIO_ICRBA_B		0x004005e8	/* IO CRB Entry A_B */
+#define		IIO_ICRBA_C		0x004005f0	/* IO CRB Entry A_C */
+#define		IIO_ICRBA_D		0x004005f8	/* IO CRB Entry A_D */
+#define		IIO_ICRBA_E		0x00400600	/* IO CRB Entry A_E */
 
-#define    IIO_ICRBA_A               0x004005e0    /* IO CRB Entry A_A       */
-#define    IIO_ICRBA_B               0x004005e8    /* IO CRB Entry A_B       */
-#define    IIO_ICRBA_C               0x004005f0    /* IO CRB Entry A_C       */
-#define    IIO_ICRBA_D               0x004005f8    /* IO CRB Entry A_D       */
-#define    IIO_ICRBA_E               0x00400600    /* IO CRB Entry A_E       */
+#define		IIO_ICRBB_A		0x00400610	/* IO CRB Entry B_A */
+#define		IIO_ICRBB_B		0x00400618	/* IO CRB Entry B_B */
+#define		IIO_ICRBB_C		0x00400620	/* IO CRB Entry B_C */
+#define		IIO_ICRBB_D		0x00400628	/* IO CRB Entry B_D */
+#define		IIO_ICRBB_E		0x00400630	/* IO CRB Entry B_E */
 
-#define    IIO_ICRBB_A               0x00400610    /* IO CRB Entry B_A       */
-#define    IIO_ICRBB_B               0x00400618    /* IO CRB Entry B_B       */
-#define    IIO_ICRBB_C               0x00400620    /* IO CRB Entry B_C       */
-#define    IIO_ICRBB_D               0x00400628    /* IO CRB Entry B_D       */
-#define    IIO_ICRBB_E               0x00400630    /* IO CRB Entry B_E       */
+#define		IIO_ICRBC_A		0x00400640	/* IO CRB Entry C_A */
+#define		IIO_ICRBC_B		0x00400648	/* IO CRB Entry C_B */
+#define		IIO_ICRBC_C		0x00400650	/* IO CRB Entry C_C */
+#define		IIO_ICRBC_D		0x00400658	/* IO CRB Entry C_D */
+#define		IIO_ICRBC_E		0x00400660	/* IO CRB Entry C_E */
 
-#define    IIO_ICRBC_A               0x00400640    /* IO CRB Entry C_A       */
-#define    IIO_ICRBC_B               0x00400648    /* IO CRB Entry C_B       */
-#define    IIO_ICRBC_C               0x00400650    /* IO CRB Entry C_C       */
-#define    IIO_ICRBC_D               0x00400658    /* IO CRB Entry C_D       */
-#define    IIO_ICRBC_E               0x00400660    /* IO CRB Entry C_E       */
+#define		IIO_ICRBD_A		0x00400670	/* IO CRB Entry D_A */
+#define		IIO_ICRBD_B		0x00400678	/* IO CRB Entry D_B */
+#define		IIO_ICRBD_C		0x00400680	/* IO CRB Entry D_C */
+#define		IIO_ICRBD_D		0x00400688	/* IO CRB Entry D_D */
+#define		IIO_ICRBD_E		0x00400690	/* IO CRB Entry D_E */
 
-#define    IIO_ICRBD_A               0x00400670    /* IO CRB Entry D_A       */
-#define    IIO_ICRBD_B               0x00400678    /* IO CRB Entry D_B       */
-#define    IIO_ICRBD_C               0x00400680    /* IO CRB Entry D_C       */
-#define    IIO_ICRBD_D               0x00400688    /* IO CRB Entry D_D       */
-#define    IIO_ICRBD_E               0x00400690    /* IO CRB Entry D_E       */
+#define		IIO_ICRBE_A		0x004006a0	/* IO CRB Entry E_A */
+#define		IIO_ICRBE_B		0x004006a8	/* IO CRB Entry E_B */
+#define		IIO_ICRBE_C		0x004006b0	/* IO CRB Entry E_C */
+#define		IIO_ICRBE_D		0x004006b8	/* IO CRB Entry E_D */
+#define		IIO_ICRBE_E		0x004006c0	/* IO CRB Entry E_E */
 
-#define    IIO_ICRBE_A               0x004006a0    /* IO CRB Entry E_A       */
-#define    IIO_ICRBE_B               0x004006a8    /* IO CRB Entry E_B       */
-#define    IIO_ICRBE_C               0x004006b0    /* IO CRB Entry E_C       */
-#define    IIO_ICRBE_D               0x004006b8    /* IO CRB Entry E_D       */
-#define    IIO_ICRBE_E               0x004006c0    /* IO CRB Entry E_E       */
+#define		IIO_ICSML		0x00400700	/* IO CRB Spurious Message Low */
+#define		IIO_ICSMM		0x00400708	/* IO CRB Spurious Message Middle */
+#define		IIO_ICSMH		0x00400710	/* IO CRB Spurious Message High */
 
-#define    IIO_ICSML                 0x00400700    /* IO CRB Spurious Message Low */
-#define    IIO_ICSMM                 0x00400708    /* IO CRB Spurious Message Middle */
-#define    IIO_ICSMH                 0x00400710    /* IO CRB Spurious Message High */
+#define		IIO_IDBSS		0x00400718	/* IO Debug Submenu Select */
 
-#define    IIO_IDBSS                 0x00400718    /* IO Debug Submenu Select */
+#define		IIO_IBLS0		0x00410000	/* IO BTE Length Status 0 */
+#define		IIO_IBSA0		0x00410008	/* IO BTE Source Address 0 */
+#define		IIO_IBDA0		0x00410010	/* IO BTE Destination Address 0 */
+#define		IIO_IBCT0		0x00410018	/* IO BTE Control Terminate 0 */
+#define		IIO_IBNA0		0x00410020	/* IO BTE Notification Address 0 */
+#define		IIO_IBIA0		0x00410028	/* IO BTE Interrupt Address 0 */
+#define		IIO_IBLS1		0x00420000	/* IO BTE Length Status 1 */
+#define		IIO_IBSA1		0x00420008	/* IO BTE Source Address 1 */
+#define		IIO_IBDA1		0x00420010	/* IO BTE Destination Address 1 */
+#define		IIO_IBCT1		0x00420018	/* IO BTE Control Terminate 1 */
+#define		IIO_IBNA1		0x00420020	/* IO BTE Notification Address 1 */
+#define		IIO_IBIA1		0x00420028	/* IO BTE Interrupt Address 1 */
 
-#define    IIO_IBLS0                 0x00410000    /* IO BTE Length Status 0 */
-#define    IIO_IBSA0                 0x00410008    /* IO BTE Source Address 0 */
-#define    IIO_IBDA0                 0x00410010    /* IO BTE Destination Address 0 */
-#define    IIO_IBCT0                 0x00410018    /* IO BTE Control Terminate 0 */
-#define    IIO_IBNA0                 0x00410020    /* IO BTE Notification Address 0 */
-#define    IIO_IBIA0                 0x00410028    /* IO BTE Interrupt Address 0 */
-#define    IIO_IBLS1                 0x00420000    /* IO BTE Length Status 1 */
-#define    IIO_IBSA1                 0x00420008    /* IO BTE Source Address 1 */
-#define    IIO_IBDA1                 0x00420010    /* IO BTE Destination Address 1 */
-#define    IIO_IBCT1                 0x00420018    /* IO BTE Control Terminate 1 */
-#define    IIO_IBNA1                 0x00420020    /* IO BTE Notification Address 1 */
-#define    IIO_IBIA1                 0x00420028    /* IO BTE Interrupt Address 1 */
-
-#define    IIO_IPCR                  0x00430000    /* IO Performance Control */
-#define    IIO_IPPR                  0x00430008    /* IO Performance Profiling */
-
+#define		IIO_IPCR		0x00430000	/* IO Performance Control */
+#define		IIO_IPPR		0x00430008	/* IO Performance Profiling */
 
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register echoes some information from the         *
  * LB_REV_ID register. It is available through Crosstalk as described   *
  * above. The REV_NUM and MFG_NUM fields receive their values from      *
  * the REVISION and MANUFACTURER fields in the LB_REV_ID register.      *
  * The PART_NUM field's value is the Crosstalk device ID number that    *
  * Steve Miller assigned to the SHub chip.                              *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_wid_u {
-	uint64_t	ii_wid_regval;
-	struct	{
-		uint64_t	w_rsvd_1		  :	 1;
-		uint64_t	w_mfg_num		  :	11;
-		uint64_t	w_part_num		  :	16;
-		uint64_t	w_rev_num		  :	 4;
-		uint64_t	w_rsvd			  :	32;
+	uint64_t ii_wid_regval;
+	struct {
+		uint64_t w_rsvd_1:1;
+		uint64_t w_mfg_num:11;
+		uint64_t w_part_num:16;
+		uint64_t w_rev_num:4;
+		uint64_t w_rsvd:32;
 	} ii_wid_fld_s;
 } ii_wid_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  The fields in this register are set upon detection of an error      *
  * and cleared by various mechanisms, as explained in the               *
  * description.                                                         *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_wstat_u {
-	uint64_t	ii_wstat_regval;
-	struct	{
-		uint64_t	w_pending		  :	 4;
-		uint64_t	w_xt_crd_to		  :	 1;
-		uint64_t	w_xt_tail_to		  :	 1;
-		uint64_t	w_rsvd_3		  :	 3;
-		uint64_t       w_tx_mx_rty               :      1;
-		uint64_t	w_rsvd_2		  :	 6;
-		uint64_t	w_llp_tx_cnt		  :	 8;
-		uint64_t	w_rsvd_1		  :	 8;
-		uint64_t	w_crazy			  :	 1;
-		uint64_t	w_rsvd			  :	31;
+	uint64_t ii_wstat_regval;
+	struct {
+		uint64_t w_pending:4;
+		uint64_t w_xt_crd_to:1;
+		uint64_t w_xt_tail_to:1;
+		uint64_t w_rsvd_3:3;
+		uint64_t w_tx_mx_rty:1;
+		uint64_t w_rsvd_2:6;
+		uint64_t w_llp_tx_cnt:8;
+		uint64_t w_rsvd_1:8;
+		uint64_t w_crazy:1;
+		uint64_t w_rsvd:31;
 	} ii_wstat_fld_s;
 } ii_wstat_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This is a read-write enabled register. It controls     *
  * various aspects of the Crosstalk flow control.                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_wcr_u {
-	uint64_t	ii_wcr_regval;
-	struct	{
-		uint64_t	w_wid			  :	 4;
-		uint64_t	w_tag			  :	 1;
-		uint64_t	w_rsvd_1		  :	 8;
-		uint64_t	w_dst_crd		  :	 3;
-		uint64_t	w_f_bad_pkt		  :	 1;
-		uint64_t	w_dir_con		  :	 1;
-		uint64_t	w_e_thresh		  :	 5;
-		uint64_t	w_rsvd			  :	41;
+	uint64_t ii_wcr_regval;
+	struct {
+		uint64_t w_wid:4;
+		uint64_t w_tag:1;
+		uint64_t w_rsvd_1:8;
+		uint64_t w_dst_crd:3;
+		uint64_t w_f_bad_pkt:1;
+		uint64_t w_dir_con:1;
+		uint64_t w_e_thresh:5;
+		uint64_t w_rsvd:41;
 	} ii_wcr_fld_s;
 } ii_wcr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register's value is a bit vector that guards      *
  * access to local registers within the II as well as to external       *
  * Crosstalk widgets. Each bit in the register corresponds to a         *
@@ -311,21 +306,18 @@
  * region ID bits are enabled in this same register. It can also be     *
  * accessed through the IAlias space by the local processors.           *
  * The reset value of this register allows access by all nodes.         *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ilapr_u {
-	uint64_t	ii_ilapr_regval;
-	struct  {
-		uint64_t	i_region                  :	64;
+	uint64_t ii_ilapr_regval;
+	struct {
+		uint64_t i_region:64;
 	} ii_ilapr_fld_s;
 } ii_ilapr_u_t;
 
-
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  A write to this register of the 64-bit value           *
  * "SGIrules" in ASCII, will cause the bit in the ILAPR register        *
  * corresponding to the region of the requestor to be set (allow        *
@@ -334,59 +326,54 @@
  * This register can also be accessed through the IAlias space.         *
  * However, this access will not change the access permissions in the   *
  * ILAPR.                                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ilapo_u {
-	uint64_t	ii_ilapo_regval;
-	struct	{
-		uint64_t	i_io_ovrride            :	64;
+	uint64_t ii_ilapo_regval;
+	struct {
+		uint64_t i_io_ovrride:64;
 	} ii_ilapo_fld_s;
 } ii_ilapo_u_t;
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register qualifies all the PIO and Graphics writes launched    *
  * from the SHUB towards a widget.                                      *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iowa_u {
-	uint64_t	ii_iowa_regval;
-	struct	{
-		uint64_t	i_w0_oac		  :	 1;
-		uint64_t	i_rsvd_1		  :	 7;
-                uint64_t       i_wx_oac                  :      8;
-		uint64_t	i_rsvd			  :	48;
+	uint64_t ii_iowa_regval;
+	struct {
+		uint64_t i_w0_oac:1;
+		uint64_t i_rsvd_1:7;
+		uint64_t i_wx_oac:8;
+		uint64_t i_rsvd:48;
 	} ii_iowa_fld_s;
 } ii_iowa_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register qualifies all the requests launched      *
  * from a widget towards the Shub. This register is intended to be      *
  * used by software in case of misbehaving widgets.                     *
- *                                                                      *
- *                                                                      *
+ *									*
+ *									*
  ************************************************************************/
 
 typedef union ii_iiwa_u {
-	uint64_t	ii_iiwa_regval;
-	struct  {
-		uint64_t	i_w0_iac                  :	 1;
-		uint64_t	i_rsvd_1		  :	 7;
-		uint64_t	i_wx_iac		  :	 8;
-		uint64_t	i_rsvd			  :	48;
+	uint64_t ii_iiwa_regval;
+	struct {
+		uint64_t i_w0_iac:1;
+		uint64_t i_rsvd_1:7;
+		uint64_t i_wx_iac:8;
+		uint64_t i_rsvd:48;
 	} ii_iiwa_fld_s;
 } ii_iiwa_u_t;
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register qualifies all the operations launched    *
  * from a widget towards the SHub. It allows individual access          *
  * control for up to 8 devices per widget. A device refers to           *
@@ -401,72 +388,69 @@
  * The bits in this field are set by writing a 1 to them. Incoming      *
  * replies from Crosstalk are not subject to this access control        *
  * mechanism.                                                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iidem_u {
-	uint64_t	ii_iidem_regval;
-	struct	{
-		uint64_t	i_w8_dxs		  :	 8;
-		uint64_t	i_w9_dxs		  :	 8;
-		uint64_t	i_wa_dxs		  :	 8;
-		uint64_t	i_wb_dxs		  :	 8;
-		uint64_t	i_wc_dxs		  :	 8;
-		uint64_t	i_wd_dxs		  :	 8;
-		uint64_t	i_we_dxs		  :	 8;
-		uint64_t	i_wf_dxs		  :	 8;
+	uint64_t ii_iidem_regval;
+	struct {
+		uint64_t i_w8_dxs:8;
+		uint64_t i_w9_dxs:8;
+		uint64_t i_wa_dxs:8;
+		uint64_t i_wb_dxs:8;
+		uint64_t i_wc_dxs:8;
+		uint64_t i_wd_dxs:8;
+		uint64_t i_we_dxs:8;
+		uint64_t i_wf_dxs:8;
 	} ii_iidem_fld_s;
 } ii_iidem_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the various programmable fields necessary    *
  * for controlling and observing the LLP signals.                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ilcsr_u {
-	uint64_t	ii_ilcsr_regval;
-	struct  {
-		uint64_t	i_nullto                  :	 6;
-		uint64_t	i_rsvd_4		  :	 2;
-		uint64_t	i_wrmrst		  :	 1;
-		uint64_t	i_rsvd_3		  :	 1;
-		uint64_t	i_llp_en		  :	 1;
-		uint64_t	i_bm8			  :	 1;
-		uint64_t	i_llp_stat		  :	 2;
-		uint64_t	i_remote_power		  :	 1;
-		uint64_t	i_rsvd_2		  :	 1;
-		uint64_t	i_maxrtry		  :	10;
-		uint64_t	i_d_avail_sel		  :	 2;
-		uint64_t	i_rsvd_1		  :	 4;
-		uint64_t	i_maxbrst		  :	10;
-                uint64_t       i_rsvd                    :     22;
+	uint64_t ii_ilcsr_regval;
+	struct {
+		uint64_t i_nullto:6;
+		uint64_t i_rsvd_4:2;
+		uint64_t i_wrmrst:1;
+		uint64_t i_rsvd_3:1;
+		uint64_t i_llp_en:1;
+		uint64_t i_bm8:1;
+		uint64_t i_llp_stat:2;
+		uint64_t i_remote_power:1;
+		uint64_t i_rsvd_2:1;
+		uint64_t i_maxrtry:10;
+		uint64_t i_d_avail_sel:2;
+		uint64_t i_rsvd_1:4;
+		uint64_t i_maxbrst:10;
+		uint64_t i_rsvd:22;
 
 	} ii_ilcsr_fld_s;
 } ii_ilcsr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This is simply a status registers that monitors the LLP error       *
- * rate.                                                                *
- *                                                                      *
+ * rate.								*
+ *									*
  ************************************************************************/
 
 typedef union ii_illr_u {
-	uint64_t	ii_illr_regval;
-	struct	{
-		uint64_t	i_sn_cnt		  :	16;
-		uint64_t	i_cb_cnt		  :	16;
-		uint64_t	i_rsvd			  :	32;
+	uint64_t ii_illr_regval;
+	struct {
+		uint64_t i_sn_cnt:16;
+		uint64_t i_cb_cnt:16;
+		uint64_t i_rsvd:32;
 	} ii_illr_fld_s;
 } ii_illr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  All II-detected non-BTE error interrupts are           *
  * specified via this register.                                         *
  * NOTE: The PI interrupt register address is hardcoded in the II. If   *
@@ -476,107 +460,100 @@
  * PI_ID==1, then the II sends the interrupt request to address         *
  * offset 0x01A0_0090 within the local register address space of PI1    *
  * on the node specified by the NODE field.                             *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iidsr_u {
-	uint64_t	ii_iidsr_regval;
-	struct  {
-		uint64_t	i_level                   :	 8;
-		uint64_t	i_pi_id			  :	 1;
-		uint64_t	i_node			  :	11;
-		uint64_t       i_rsvd_3                  :      4;
-		uint64_t	i_enable		  :	 1;
-		uint64_t	i_rsvd_2		  :	 3;
-		uint64_t	i_int_sent		  :	 2;
-		uint64_t       i_rsvd_1                  :      2;
-		uint64_t	i_pi0_forward_int	  :	 1;
-		uint64_t	i_pi1_forward_int	  :	 1;
-		uint64_t	i_rsvd			  :	30;
+	uint64_t ii_iidsr_regval;
+	struct {
+		uint64_t i_level:8;
+		uint64_t i_pi_id:1;
+		uint64_t i_node:11;
+		uint64_t i_rsvd_3:4;
+		uint64_t i_enable:1;
+		uint64_t i_rsvd_2:3;
+		uint64_t i_int_sent:2;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_pi0_forward_int:1;
+		uint64_t i_pi1_forward_int:1;
+		uint64_t i_rsvd:30;
 	} ii_iidsr_fld_s;
 } ii_iidsr_u_t;
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are two instances of this register. This register is used     *
  * for matching up the incoming responses from the graphics widget to   *
  * the processor that initiated the graphics operation. The             *
  * write-responses are converted to graphics credits and returned to    *
  * the processor so that the processor interface can manage the flow    *
  * control.                                                             *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_igfx0_u {
-	uint64_t	ii_igfx0_regval;
-	struct	{
-		uint64_t	i_w_num			  :	 4;
-		uint64_t       i_pi_id                   :      1;
-		uint64_t	i_n_num			  :	12;
-		uint64_t       i_p_num                   :      1;
-		uint64_t       i_rsvd                    :     46;
+	uint64_t ii_igfx0_regval;
+	struct {
+		uint64_t i_w_num:4;
+		uint64_t i_pi_id:1;
+		uint64_t i_n_num:12;
+		uint64_t i_p_num:1;
+		uint64_t i_rsvd:46;
 	} ii_igfx0_fld_s;
 } ii_igfx0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are two instances of this register. This register is used     *
  * for matching up the incoming responses from the graphics widget to   *
  * the processor that initiated the graphics operation. The             *
  * write-responses are converted to graphics credits and returned to    *
  * the processor so that the processor interface can manage the flow    *
  * control.                                                             *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_igfx1_u {
-	uint64_t	ii_igfx1_regval;
-	struct  {
-		uint64_t	i_w_num			  :	 4;
-		uint64_t       i_pi_id                   :      1;
-		uint64_t	i_n_num			  :	12;
-		uint64_t       i_p_num                   :      1;
-		uint64_t       i_rsvd                    :     46;
+	uint64_t ii_igfx1_regval;
+	struct {
+		uint64_t i_w_num:4;
+		uint64_t i_pi_id:1;
+		uint64_t i_n_num:12;
+		uint64_t i_p_num:1;
+		uint64_t i_rsvd:46;
 	} ii_igfx1_fld_s;
 } ii_igfx1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are two instances of this registers. These registers are      *
  * used as scratch registers for software use.                          *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iscr0_u {
-	uint64_t	ii_iscr0_regval;
-	struct  {
-		uint64_t	i_scratch                 :	64;
+	uint64_t ii_iscr0_regval;
+	struct {
+		uint64_t i_scratch:64;
 	} ii_iscr0_fld_s;
 } ii_iscr0_u_t;
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are two instances of this registers. These registers are      *
  * used as scratch registers for software use.                          *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iscr1_u {
-	uint64_t	ii_iscr1_regval;
-	struct  {
-		uint64_t	i_scratch                 :	64;
+	uint64_t ii_iscr1_regval;
+	struct {
+		uint64_t i_scratch:64;
 	} ii_iscr1_fld_s;
 } ii_iscr1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a Shub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -599,23 +576,22 @@
  * Crosstalk space addressable by the Shub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte1_u {
-	uint64_t	ii_itte1_regval;
-	struct  {
-		uint64_t	i_offset                  :	 5;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_w_num			  :	 4;
-		uint64_t	i_iosp			  :	 1;
-		uint64_t	i_rsvd			  :	51;
+	uint64_t ii_itte1_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte1_fld_s;
 } ii_itte1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a Shub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -638,23 +614,22 @@
  * Crosstalk space addressable by the Shub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte2_u {
-	uint64_t	ii_itte2_regval;
-	struct	{
-		uint64_t	i_offset		  :	 5;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_w_num			  :	 4;
-		uint64_t	i_iosp			  :	 1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_itte2_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte2_fld_s;
 } ii_itte2_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a Shub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -677,23 +652,22 @@
  * Crosstalk space addressable by the SHub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte3_u {
-	uint64_t	ii_itte3_regval;
-	struct  {
-		uint64_t	i_offset                  :	 5;
-		uint64_t       i_rsvd_1                  :      3;
-		uint64_t       i_w_num                   :      4;
-		uint64_t       i_iosp                    :      1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_itte3_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte3_fld_s;
 } ii_itte3_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a SHub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -716,23 +690,22 @@
  * Crosstalk space addressable by the SHub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte4_u {
-	uint64_t	ii_itte4_regval;
-	struct  {
-		uint64_t	i_offset                  :	 5;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t       i_w_num                   :      4;
-		uint64_t       i_iosp                    :      1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_itte4_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte4_fld_s;
 } ii_itte4_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a SHub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -755,23 +728,22 @@
  * Crosstalk space addressable by the Shub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte5_u {
-	uint64_t	ii_itte5_regval;
-	struct  {
-		uint64_t	i_offset                  :	 5;
-		uint64_t       i_rsvd_1                  :      3;
-		uint64_t       i_w_num                   :      4;
-		uint64_t       i_iosp                    :      1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_itte5_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte5_fld_s;
 } ii_itte5_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a Shub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -794,23 +766,22 @@
  * Crosstalk space addressable by the Shub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte6_u {
-	uint64_t	ii_itte6_regval;
-	struct  {
-		uint64_t	i_offset                  :	 5;
-		uint64_t       i_rsvd_1                  :      3;
-		uint64_t       i_w_num                   :      4;
-		uint64_t       i_iosp                    :      1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_itte6_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte6_fld_s;
 } ii_itte6_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are seven instances of translation table entry   *
  * registers. Each register maps a Shub Big Window to a 48-bit          *
  * address on Crosstalk.                                                *
@@ -833,23 +804,22 @@
  * Crosstalk space addressable by the SHub is thus the lower            *
  * 8-GBytes per widget (N-mode), only <SUP >7</SUP>/<SUB >32nds</SUB>   *
  * of this space can be accessed.                                       *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_itte7_u {
-	uint64_t	ii_itte7_regval;
-	struct  {
-		uint64_t	i_offset                  :	 5;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t       i_w_num                   :      4;
-		uint64_t       i_iosp                    :      1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_itte7_regval;
+	struct {
+		uint64_t i_offset:5;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_w_num:4;
+		uint64_t i_iosp:1;
+		uint64_t i_rsvd:51;
 	} ii_itte7_fld_s;
 } ii_itte7_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -868,33 +838,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprb0_u {
-	uint64_t	ii_iprb0_regval;
-	struct  {
-		uint64_t	i_c                       :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t       i_rsvd_2                  :      2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprb0_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprb0_fld_s;
 } ii_iprb0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -913,33 +882,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprb8_u {
-	uint64_t	ii_iprb8_regval;
-	struct  {
-		uint64_t	i_c                       :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t       i_rsvd_2                  :      2;
-		uint64_t	i_nb			  :	14;
-		uint64_t       i_rsvd_1                  :      2;
-		uint64_t       i_m                       :      2;
-		uint64_t       i_f                       :      1;
-		uint64_t       i_of_cnt                  :      5;
-		uint64_t       i_error                   :      1;
-		uint64_t       i_rd_to                   :      1;
-		uint64_t       i_spur_wr                 :      1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t       i_rsvd                    :     11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprb8_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprb8_fld_s;
 } ii_iprb8_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -958,33 +926,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprb9_u {
-	uint64_t	ii_iprb9_regval;
-	struct	{
-		uint64_t	i_c			  :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t	i_rsvd_2		  :	 2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprb9_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprb9_fld_s;
 } ii_iprb9_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.        *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -1003,33 +970,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- *                                                                      *
- *                                                                      *
+ *									*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprba_u {
-	uint64_t	ii_iprba_regval;
-	struct  {
-		uint64_t	i_c                       :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t       i_rsvd_2                  :      2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprba_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprba_fld_s;
 } ii_iprba_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -1048,33 +1014,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprbb_u {
-	uint64_t	ii_iprbb_regval;
-	struct	{
-		uint64_t	i_c			  :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t	i_rsvd_2		  :	 2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprbb_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprbb_fld_s;
 } ii_iprbb_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -1093,33 +1058,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprbc_u {
-	uint64_t	ii_iprbc_regval;
-	struct	{
-		uint64_t	i_c			  :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t	i_rsvd_2		  :	 2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprbc_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprbc_fld_s;
 } ii_iprbc_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -1138,33 +1102,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprbd_u {
-	uint64_t	ii_iprbd_regval;
-	struct	{
-		uint64_t	i_c			  :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t	i_rsvd_2		  :	 2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprbd_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprbd_fld_s;
 } ii_iprbd_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of SHub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -1183,33 +1146,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprbe_u {
-	uint64_t	ii_iprbe_regval;
-	struct	{
-		uint64_t	i_c			  :	 8;
-		uint64_t	i_na			  :	14;
-		uint64_t	i_rsvd_2		  :	 2;
-		uint64_t	i_nb			  :	14;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_m			  :	 2;
-		uint64_t	i_f			  :	 1;
-		uint64_t	i_of_cnt		  :	 5;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rd_to			  :	 1;
-		uint64_t	i_spur_wr		  :	 1;
-		uint64_t	i_spur_rd		  :	 1;
-		uint64_t	i_rsvd			  :	11;
-		uint64_t	i_mult_err		  :	 1;
+	uint64_t ii_iprbe_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
 	} ii_iprbe_fld_s;
 } ii_iprbe_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 9 instances of this register, one per        *
  * actual widget in this implementation of Shub and Crossbow.           *
  * Note: Crossbow only has ports for Widgets 8 through F, widget 0      *
@@ -1228,33 +1190,32 @@
  * register; the write will correct the C field and capture its new     *
  * value in the internal register. Even if IECLR[E_PRB_x] is set, the   *
  * SPUR_WR bit will persist if IPRBx hasn't yet been written.           *
- * .                                                                    *
- *                                                                      *
+ * .    								*
+ *									*
  ************************************************************************/
 
 typedef union ii_iprbf_u {
-        uint64_t       ii_iprbf_regval;
-        struct  {
-                uint64_t       i_c                       :      8;
-                uint64_t       i_na                      :     14;
-                uint64_t       i_rsvd_2                  :      2;
-                uint64_t       i_nb                      :     14;
-                uint64_t       i_rsvd_1                  :      2;
-                uint64_t       i_m                       :      2;
-                uint64_t       i_f                       :      1;
-                uint64_t       i_of_cnt                  :      5;
-                uint64_t       i_error                   :      1;
-                uint64_t       i_rd_to                   :      1;
-                uint64_t       i_spur_wr                 :      1;
-                uint64_t       i_spur_rd                 :      1;
-                uint64_t       i_rsvd                    :     11;
-                uint64_t       i_mult_err                :      1;
-        } ii_iprbe_fld_s;
+	uint64_t ii_iprbf_regval;
+	struct {
+		uint64_t i_c:8;
+		uint64_t i_na:14;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_nb:14;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_m:2;
+		uint64_t i_f:1;
+		uint64_t i_of_cnt:5;
+		uint64_t i_error:1;
+		uint64_t i_rd_to:1;
+		uint64_t i_spur_wr:1;
+		uint64_t i_spur_rd:1;
+		uint64_t i_rsvd:11;
+		uint64_t i_mult_err:1;
+	} ii_iprbe_fld_s;
 } ii_iprbf_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register specifies the timeout value to use for monitoring     *
  * Crosstalk credits which are used outbound to Crosstalk. An           *
  * internal counter called the Crosstalk Credit Timeout Counter         *
@@ -1267,20 +1228,19 @@
  * Crosstalk Credit Timeout has occurred. The internal counter is not   *
  * readable from software, and stops counting at its maximum value,     *
  * so it cannot cause more than one interrupt.                          *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ixcc_u {
-	uint64_t	ii_ixcc_regval;
-	struct  {
-		uint64_t	i_time_out                :	26;
-		uint64_t	i_rsvd			  :	38;
+	uint64_t ii_ixcc_regval;
+	struct {
+		uint64_t i_time_out:26;
+		uint64_t i_rsvd:38;
 	} ii_ixcc_fld_s;
 } ii_ixcc_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register qualifies all the PIO and DMA            *
  * operations launched from widget 0 towards the SHub. In               *
  * addition, it also qualifies accesses by the BTE streams.             *
@@ -1292,27 +1252,25 @@
  * the Wx_IAC field. The bits in this field are set by writing a 1 to   *
  * them. Incoming replies from Crosstalk are not subject to this        *
  * access control mechanism.                                            *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_imem_u {
-	uint64_t	ii_imem_regval;
-	struct  {
-		uint64_t	i_w0_esd                  :	 1;
-		uint64_t	i_rsvd_3		  :	 3;
-		uint64_t	i_b0_esd		  :	 1;
-		uint64_t	i_rsvd_2		  :	 3;
-		uint64_t	i_b1_esd		  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_clr_precise		  :	 1;
-		uint64_t       i_rsvd                    :     51;
+	uint64_t ii_imem_regval;
+	struct {
+		uint64_t i_w0_esd:1;
+		uint64_t i_rsvd_3:3;
+		uint64_t i_b0_esd:1;
+		uint64_t i_rsvd_2:3;
+		uint64_t i_b1_esd:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_clr_precise:1;
+		uint64_t i_rsvd:51;
 	} ii_imem_fld_s;
 } ii_imem_u_t;
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register specifies the timeout value to use for   *
  * monitoring Crosstalk tail flits coming into the Shub in the          *
  * TAIL_TO field. An internal counter associated with this register     *
@@ -1332,90 +1290,87 @@
  * the value in the RRSP_TO field, a Read Response Timeout has          *
  * occurred, and error handling occurs as described in the Error        *
  * Handling section of this document.                                   *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ixtt_u {
-	uint64_t	ii_ixtt_regval;
-	struct  {
-		uint64_t	i_tail_to                 :	26;
-		uint64_t	i_rsvd_1		  :	 6;
-		uint64_t	i_rrsp_ps		  :	23;
-		uint64_t	i_rrsp_to		  :	 5;
-		uint64_t	i_rsvd			  :	 4;
+	uint64_t ii_ixtt_regval;
+	struct {
+		uint64_t i_tail_to:26;
+		uint64_t i_rsvd_1:6;
+		uint64_t i_rrsp_ps:23;
+		uint64_t i_rrsp_to:5;
+		uint64_t i_rsvd:4;
 	} ii_ixtt_fld_s;
 } ii_ixtt_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  Writing a 1 to the fields of this register clears the appropriate   *
  * error bits in other areas of SHub. Note that when the                *
  * E_PRB_x bits are used to clear error bits in PRB registers,          *
  * SPUR_RD and SPUR_WR may persist, because they require additional     *
  * action to clear them. See the IPRBx and IXSS Register                *
  * specifications.                                                      *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ieclr_u {
-	uint64_t	ii_ieclr_regval;
-	struct  {
-		uint64_t	i_e_prb_0                 :	 1;
-		uint64_t	i_rsvd			  :	 7;
-		uint64_t	i_e_prb_8		  :	 1;
-		uint64_t	i_e_prb_9		  :	 1;
-		uint64_t	i_e_prb_a		  :	 1;
-		uint64_t	i_e_prb_b		  :	 1;
-		uint64_t	i_e_prb_c		  :	 1;
-		uint64_t	i_e_prb_d		  :	 1;
-		uint64_t	i_e_prb_e		  :	 1;
-		uint64_t	i_e_prb_f		  :	 1;
-		uint64_t	i_e_crazy		  :	 1;
-		uint64_t	i_e_bte_0		  :	 1;
-		uint64_t	i_e_bte_1		  :	 1;
-		uint64_t	i_reserved_1		  :	10;
-		uint64_t	i_spur_rd_hdr		  :	 1;
-		uint64_t	i_cam_intr_to		  :	 1;
-		uint64_t	i_cam_overflow		  :	 1;
-		uint64_t	i_cam_read_miss		  :	 1;
-		uint64_t	i_ioq_rep_underflow	  :	 1;
-		uint64_t	i_ioq_req_underflow	  :	 1;
-		uint64_t	i_ioq_rep_overflow	  :	 1;
-		uint64_t	i_ioq_req_overflow	  :	 1;
-		uint64_t	i_iiq_rep_overflow	  :	 1;
-		uint64_t	i_iiq_req_overflow	  :	 1;
-		uint64_t	i_ii_xn_rep_cred_overflow :	 1;
-		uint64_t	i_ii_xn_req_cred_overflow :	 1;
-		uint64_t	i_ii_xn_invalid_cmd	  :	 1;
-		uint64_t	i_xn_ii_invalid_cmd	  :	 1;
-		uint64_t	i_reserved_2		  :	21;
+	uint64_t ii_ieclr_regval;
+	struct {
+		uint64_t i_e_prb_0:1;
+		uint64_t i_rsvd:7;
+		uint64_t i_e_prb_8:1;
+		uint64_t i_e_prb_9:1;
+		uint64_t i_e_prb_a:1;
+		uint64_t i_e_prb_b:1;
+		uint64_t i_e_prb_c:1;
+		uint64_t i_e_prb_d:1;
+		uint64_t i_e_prb_e:1;
+		uint64_t i_e_prb_f:1;
+		uint64_t i_e_crazy:1;
+		uint64_t i_e_bte_0:1;
+		uint64_t i_e_bte_1:1;
+		uint64_t i_reserved_1:10;
+		uint64_t i_spur_rd_hdr:1;
+		uint64_t i_cam_intr_to:1;
+		uint64_t i_cam_overflow:1;
+		uint64_t i_cam_read_miss:1;
+		uint64_t i_ioq_rep_underflow:1;
+		uint64_t i_ioq_req_underflow:1;
+		uint64_t i_ioq_rep_overflow:1;
+		uint64_t i_ioq_req_overflow:1;
+		uint64_t i_iiq_rep_overflow:1;
+		uint64_t i_iiq_req_overflow:1;
+		uint64_t i_ii_xn_rep_cred_overflow:1;
+		uint64_t i_ii_xn_req_cred_overflow:1;
+		uint64_t i_ii_xn_invalid_cmd:1;
+		uint64_t i_xn_ii_invalid_cmd:1;
+		uint64_t i_reserved_2:21;
 	} ii_ieclr_fld_s;
 } ii_ieclr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register controls both BTEs. SOFT_RESET is intended for        *
  * recovery after an error. COUNT controls the total number of CRBs     *
  * that both BTEs (combined) can use, which affects total BTE           *
  * bandwidth.                                                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibcr_u {
-	uint64_t	ii_ibcr_regval;
-	struct  {
-		uint64_t	i_count                   :	 4;
-		uint64_t	i_rsvd_1		  :	 4;
-		uint64_t	i_soft_reset		  :	 1;
-		uint64_t	i_rsvd			  :	55;
+	uint64_t ii_ibcr_regval;
+	struct {
+		uint64_t i_count:4;
+		uint64_t i_rsvd_1:4;
+		uint64_t i_soft_reset:1;
+		uint64_t i_rsvd:55;
 	} ii_ibcr_fld_s;
 } ii_ibcr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the header of a spurious read response       *
  * received from Crosstalk. A spurious read response is defined as a    *
  * read response received by II from a widget for which (1) the SIDN    *
@@ -1440,49 +1395,47 @@
  * will be set. Any SPUR_RD bits in any other PRB registers indicate    *
  * spurious messages from other widets which were detected after the    *
  * header was captured..                                                *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ixsm_u {
-	uint64_t	ii_ixsm_regval;
-	struct  {
-		uint64_t	i_byte_en                 :	32;
-		uint64_t	i_reserved		  :	 1;
-		uint64_t	i_tag			  :	 3;
-		uint64_t	i_alt_pactyp		  :	 4;
-		uint64_t	i_bo			  :	 1;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_vbpm			  :	 1;
-		uint64_t	i_gbr			  :	 1;
-		uint64_t	i_ds			  :	 2;
-		uint64_t	i_ct			  :	 1;
-		uint64_t	i_tnum			  :	 5;
-		uint64_t	i_pactyp		  :	 4;
-		uint64_t	i_sidn			  :	 4;
-		uint64_t	i_didn			  :	 4;
+	uint64_t ii_ixsm_regval;
+	struct {
+		uint64_t i_byte_en:32;
+		uint64_t i_reserved:1;
+		uint64_t i_tag:3;
+		uint64_t i_alt_pactyp:4;
+		uint64_t i_bo:1;
+		uint64_t i_error:1;
+		uint64_t i_vbpm:1;
+		uint64_t i_gbr:1;
+		uint64_t i_ds:2;
+		uint64_t i_ct:1;
+		uint64_t i_tnum:5;
+		uint64_t i_pactyp:4;
+		uint64_t i_sidn:4;
+		uint64_t i_didn:4;
 	} ii_ixsm_fld_s;
 } ii_ixsm_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the sideband bits of a spurious read         *
  * response received from Crosstalk.                                    *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ixss_u {
-	uint64_t	ii_ixss_regval;
-	struct  {
-		uint64_t	i_sideband                :	 8;
-		uint64_t	i_rsvd			  :	55;
-		uint64_t	i_valid			  :	 1;
+	uint64_t ii_ixss_regval;
+	struct {
+		uint64_t i_sideband:8;
+		uint64_t i_rsvd:55;
+		uint64_t i_valid:1;
 	} ii_ixss_fld_s;
 } ii_ixss_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register enables software to access the II LLP's test port.    *
  * Refer to the LLP 2.5 documentation for an explanation of the test    *
  * port. Software can write to this register to program the values      *
@@ -1490,27 +1443,26 @@
  * TestMask and TestSeed). Similarly, software can read from this       *
  * register to obtain the values of the test port's status outputs      *
  * (TestCBerr, TestValid and TestData).                                 *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ilct_u {
-	uint64_t	ii_ilct_regval;
-	struct  {
-		uint64_t	i_test_seed               :	20;
-		uint64_t	i_test_mask               :	 8;
-		uint64_t	i_test_data               :	20;
-		uint64_t	i_test_valid              :	 1;
-		uint64_t	i_test_cberr              :	 1;
-		uint64_t	i_test_flit               :	 3;
-		uint64_t	i_test_clear              :	 1;
-		uint64_t	i_test_err_capture        :	 1;
-		uint64_t	i_rsvd                    :	 9;
+	uint64_t ii_ilct_regval;
+	struct {
+		uint64_t i_test_seed:20;
+		uint64_t i_test_mask:8;
+		uint64_t i_test_data:20;
+		uint64_t i_test_valid:1;
+		uint64_t i_test_cberr:1;
+		uint64_t i_test_flit:3;
+		uint64_t i_test_clear:1;
+		uint64_t i_test_err_capture:1;
+		uint64_t i_rsvd:9;
 	} ii_ilct_fld_s;
 } ii_ilct_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  If the II detects an illegal incoming Duplonet packet (request or   *
  * reply) when VALID==0 in the IIEPH1 register, then it saves the       *
  * contents of the packet's header flit in the IIEPH1 and IIEPH2        *
@@ -1526,575 +1478,549 @@
  * packet when VALID==1 in the IIEPH1 register, then it merely sets     *
  * the OVERRUN bit to indicate that a subsequent error has happened,    *
  * and does nothing further.                                            *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iieph1_u {
-	uint64_t	ii_iieph1_regval;
-	struct	{
-		uint64_t	i_command		  :	 7;
-		uint64_t	i_rsvd_5		  :	 1;
-		uint64_t	i_suppl			  :	14;
-		uint64_t	i_rsvd_4		  :	 1;
-		uint64_t	i_source		  :	14;
-		uint64_t	i_rsvd_3		  :	 1;
-		uint64_t	i_err_type		  :	 4;
-		uint64_t	i_rsvd_2		  :	 4;
-		uint64_t	i_overrun		  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_valid			  :	 1;
-		uint64_t	i_rsvd			  :	13;
+	uint64_t ii_iieph1_regval;
+	struct {
+		uint64_t i_command:7;
+		uint64_t i_rsvd_5:1;
+		uint64_t i_suppl:14;
+		uint64_t i_rsvd_4:1;
+		uint64_t i_source:14;
+		uint64_t i_rsvd_3:1;
+		uint64_t i_err_type:4;
+		uint64_t i_rsvd_2:4;
+		uint64_t i_overrun:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_valid:1;
+		uint64_t i_rsvd:13;
 	} ii_iieph1_fld_s;
 } ii_iieph1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register holds the Address field from the header flit of an    *
  * incoming erroneous Duplonet packet, along with the tail bit which    *
  * accompanied this header flit. This register is essentially an        *
  * extension of IIEPH1. Two registers were necessary because the 64     *
  * bits available in only a single register were insufficient to        *
  * capture the entire header flit of an erroneous packet.               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iieph2_u {
-	uint64_t	ii_iieph2_regval;
-	struct  {
-		uint64_t	i_rsvd_0		  :	 3;
-		uint64_t	i_address                 :	47;
-		uint64_t	i_rsvd_1		  :	10;
-		uint64_t	i_tail			  :	 1;
-		uint64_t	i_rsvd			  :	 3;
+	uint64_t ii_iieph2_regval;
+	struct {
+		uint64_t i_rsvd_0:3;
+		uint64_t i_address:47;
+		uint64_t i_rsvd_1:10;
+		uint64_t i_tail:1;
+		uint64_t i_rsvd:3;
 	} ii_iieph2_fld_s;
 } ii_iieph2_u_t;
 
-
 /******************************/
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register's value is a bit vector that guards access from SXBs  *
  * to local registers within the II as well as to external Crosstalk    *
  * widgets								*
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_islapr_u {
-	uint64_t	ii_islapr_regval;
-	struct  {
-		uint64_t	i_region		  :	64;
+	uint64_t ii_islapr_regval;
+	struct {
+		uint64_t i_region:64;
 	} ii_islapr_fld_s;
 } ii_islapr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  A write to this register of the 56-bit value "Pup+Bun" will cause	*
  * the bit in the ISLAPR register corresponding to the region of the	*
  * requestor to be set (access allowed).				(
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_islapo_u {
-	uint64_t	ii_islapo_regval;
-	struct  {
-		uint64_t	i_io_sbx_ovrride	  :	56;
-		uint64_t	i_rsvd			  :	 8;
+	uint64_t ii_islapo_regval;
+	struct {
+		uint64_t i_io_sbx_ovrride:56;
+		uint64_t i_rsvd:8;
 	} ii_islapo_fld_s;
 } ii_islapo_u_t;
 
 /************************************************************************
- *                                                                      *
+ *									*
  *  Determines how long the wrapper will wait aftr an interrupt is	*
  * initially issued from the II before it times out the outstanding	*
  * interrupt and drops it from the interrupt queue.			* 
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iwi_u {
-	uint64_t	ii_iwi_regval;
-	struct  {
-		uint64_t	i_prescale		  :	24;
-		uint64_t	i_rsvd			  :	 8;
-		uint64_t	i_timeout		  :	 8;
-		uint64_t	i_rsvd1			  :	 8;
-		uint64_t	i_intrpt_retry_period	  :	 8;
-		uint64_t	i_rsvd2			  :	 8;
+	uint64_t ii_iwi_regval;
+	struct {
+		uint64_t i_prescale:24;
+		uint64_t i_rsvd:8;
+		uint64_t i_timeout:8;
+		uint64_t i_rsvd1:8;
+		uint64_t i_intrpt_retry_period:8;
+		uint64_t i_rsvd2:8;
 	} ii_iwi_fld_s;
 } ii_iwi_u_t;
 
 /************************************************************************
- *                                                                      *
+ *									*
  *  Log errors which have occurred in the II wrapper. The errors are	*
  * cleared by writing to the IECLR register.				* 
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iwel_u {
-	uint64_t	ii_iwel_regval;
-	struct  {
-		uint64_t	i_intr_timed_out	  :	 1;
-		uint64_t	i_rsvd			  :	 7;
-		uint64_t	i_cam_overflow		  :	 1;
-		uint64_t	i_cam_read_miss		  :	 1;
-		uint64_t	i_rsvd1			  :	 2;
-		uint64_t	i_ioq_rep_underflow	  :	 1;
-		uint64_t	i_ioq_req_underflow	  :	 1;
-		uint64_t	i_ioq_rep_overflow	  :	 1;
-		uint64_t	i_ioq_req_overflow	  :	 1;
-		uint64_t	i_iiq_rep_overflow	  :	 1;
-		uint64_t	i_iiq_req_overflow	  :	 1;
-		uint64_t	i_rsvd2			  :	 6;
-		uint64_t	i_ii_xn_rep_cred_over_under:	 1;
-		uint64_t	i_ii_xn_req_cred_over_under:	 1;
-		uint64_t	i_rsvd3			  :	 6;
-		uint64_t	i_ii_xn_invalid_cmd	  :	 1;
-		uint64_t	i_xn_ii_invalid_cmd	  :	 1;
-		uint64_t	i_rsvd4			  :	30;
+	uint64_t ii_iwel_regval;
+	struct {
+		uint64_t i_intr_timed_out:1;
+		uint64_t i_rsvd:7;
+		uint64_t i_cam_overflow:1;
+		uint64_t i_cam_read_miss:1;
+		uint64_t i_rsvd1:2;
+		uint64_t i_ioq_rep_underflow:1;
+		uint64_t i_ioq_req_underflow:1;
+		uint64_t i_ioq_rep_overflow:1;
+		uint64_t i_ioq_req_overflow:1;
+		uint64_t i_iiq_rep_overflow:1;
+		uint64_t i_iiq_req_overflow:1;
+		uint64_t i_rsvd2:6;
+		uint64_t i_ii_xn_rep_cred_over_under:1;
+		uint64_t i_ii_xn_req_cred_over_under:1;
+		uint64_t i_rsvd3:6;
+		uint64_t i_ii_xn_invalid_cmd:1;
+		uint64_t i_xn_ii_invalid_cmd:1;
+		uint64_t i_rsvd4:30;
 	} ii_iwel_fld_s;
 } ii_iwel_u_t;
 
 /************************************************************************
- *                                                                      *
+ *									*
  *  Controls the II wrapper.						* 
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iwc_u {
-	uint64_t	ii_iwc_regval;
-	struct  {
-		uint64_t	i_dma_byte_swap		  :	 1;
-		uint64_t	i_rsvd			  :	 3;
-		uint64_t	i_cam_read_lines_reset	  :	 1;
-		uint64_t	i_rsvd1			  :	 3;
-		uint64_t	i_ii_xn_cred_over_under_log:	 1;
-		uint64_t	i_rsvd2			  :	19;
-		uint64_t	i_xn_rep_iq_depth	  :	 5;
-		uint64_t	i_rsvd3			  :	 3;
-		uint64_t	i_xn_req_iq_depth	  :	 5;
-		uint64_t	i_rsvd4			  :	 3;
-		uint64_t	i_iiq_depth		  :	 6;
-		uint64_t	i_rsvd5			  :	12;
-		uint64_t	i_force_rep_cred	  :	 1;
-		uint64_t	i_force_req_cred	  :	 1;
+	uint64_t ii_iwc_regval;
+	struct {
+		uint64_t i_dma_byte_swap:1;
+		uint64_t i_rsvd:3;
+		uint64_t i_cam_read_lines_reset:1;
+		uint64_t i_rsvd1:3;
+		uint64_t i_ii_xn_cred_over_under_log:1;
+		uint64_t i_rsvd2:19;
+		uint64_t i_xn_rep_iq_depth:5;
+		uint64_t i_rsvd3:3;
+		uint64_t i_xn_req_iq_depth:5;
+		uint64_t i_rsvd4:3;
+		uint64_t i_iiq_depth:6;
+		uint64_t i_rsvd5:12;
+		uint64_t i_force_rep_cred:1;
+		uint64_t i_force_req_cred:1;
 	} ii_iwc_fld_s;
 } ii_iwc_u_t;
 
 /************************************************************************
- *                                                                      *
+ *									*
  *  Status in the II wrapper.						* 
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iws_u {
-	uint64_t	ii_iws_regval;
-	struct  {
-		uint64_t	i_xn_rep_iq_credits	  :	 5;
-		uint64_t	i_rsvd			  :	 3;
-		uint64_t	i_xn_req_iq_credits	  :	 5;
-		uint64_t	i_rsvd1			  :	51;
+	uint64_t ii_iws_regval;
+	struct {
+		uint64_t i_xn_rep_iq_credits:5;
+		uint64_t i_rsvd:3;
+		uint64_t i_xn_req_iq_credits:5;
+		uint64_t i_rsvd1:51;
 	} ii_iws_fld_s;
 } ii_iws_u_t;
 
 /************************************************************************
- *                                                                      *
+ *									*
  *  Masks errors in the IWEL register.					*
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iweim_u {
-	uint64_t	ii_iweim_regval;
-	struct  {
-		uint64_t	i_intr_timed_out	  :	 1;
-		uint64_t	i_rsvd			  :	 7;
-		uint64_t	i_cam_overflow		  :	 1;
-		uint64_t	i_cam_read_miss		  :	 1;
-		uint64_t	i_rsvd1			  :	 2;
-		uint64_t	i_ioq_rep_underflow	  :	 1;
-		uint64_t	i_ioq_req_underflow	  :	 1;
-		uint64_t	i_ioq_rep_overflow	  :	 1;
-		uint64_t	i_ioq_req_overflow	  :	 1;
-		uint64_t	i_iiq_rep_overflow	  :	 1;
-		uint64_t	i_iiq_req_overflow	  :	 1;
-		uint64_t	i_rsvd2			  :	 6;
-		uint64_t	i_ii_xn_rep_cred_overflow :	 1;
-		uint64_t	i_ii_xn_req_cred_overflow :	 1;
-		uint64_t	i_rsvd3			  :	 6;
-		uint64_t	i_ii_xn_invalid_cmd	  :	 1;
-		uint64_t	i_xn_ii_invalid_cmd	  :	 1;
-		uint64_t	i_rsvd4			  :	30;
+	uint64_t ii_iweim_regval;
+	struct {
+		uint64_t i_intr_timed_out:1;
+		uint64_t i_rsvd:7;
+		uint64_t i_cam_overflow:1;
+		uint64_t i_cam_read_miss:1;
+		uint64_t i_rsvd1:2;
+		uint64_t i_ioq_rep_underflow:1;
+		uint64_t i_ioq_req_underflow:1;
+		uint64_t i_ioq_rep_overflow:1;
+		uint64_t i_ioq_req_overflow:1;
+		uint64_t i_iiq_rep_overflow:1;
+		uint64_t i_iiq_req_overflow:1;
+		uint64_t i_rsvd2:6;
+		uint64_t i_ii_xn_rep_cred_overflow:1;
+		uint64_t i_ii_xn_req_cred_overflow:1;
+		uint64_t i_rsvd3:6;
+		uint64_t i_ii_xn_invalid_cmd:1;
+		uint64_t i_xn_ii_invalid_cmd:1;
+		uint64_t i_rsvd4:30;
 	} ii_iweim_fld_s;
 } ii_iweim_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  A write to this register causes a particular field in the           *
  * corresponding widget's PRB entry to be adjusted up or down by 1.     *
  * This counter should be used when recovering from error and reset     *
  * conditions. Note that software would be capable of causing           *
  * inadvertent overflow or underflow of these counters.                 *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ipca_u {
-	uint64_t	ii_ipca_regval;
-	struct  {
-		uint64_t	i_wid                     :	 4;
-		uint64_t	i_adjust		  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_field			  :	 2;
-		uint64_t	i_rsvd			  :	54;
+	uint64_t ii_ipca_regval;
+	struct {
+		uint64_t i_wid:4;
+		uint64_t i_adjust:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_field:2;
+		uint64_t i_rsvd:54;
 	} ii_ipca_fld_s;
 } ii_ipca_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
-
 typedef union ii_iprte0a_u {
-	uint64_t	ii_iprte0a_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t       i_vld                     :      1;
+	uint64_t ii_iprte0a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte0a_fld_s;
 } ii_iprte0a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte1a_u {
-	uint64_t	ii_iprte1a_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t       i_vld                     :      1;
+	uint64_t ii_iprte1a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte1a_fld_s;
 } ii_iprte1a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte2a_u {
-	uint64_t	ii_iprte2a_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t       i_vld                     :      1;
+	uint64_t ii_iprte2a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte2a_fld_s;
 } ii_iprte2a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte3a_u {
-	uint64_t	ii_iprte3a_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t	i_vld			  :	 1;
+	uint64_t ii_iprte3a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte3a_fld_s;
 } ii_iprte3a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte4a_u {
-	uint64_t	ii_iprte4a_regval;
-	struct	{
-		uint64_t	i_rsvd_1		  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t	i_vld			  :	 1;
+	uint64_t ii_iprte4a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte4a_fld_s;
 } ii_iprte4a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte5a_u {
-	uint64_t	ii_iprte5a_regval;
-	struct	{
-		uint64_t	i_rsvd_1		  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t	i_vld			  :	 1;
+	uint64_t ii_iprte5a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte5a_fld_s;
 } ii_iprte5a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte6a_u {
-	uint64_t	ii_iprte6a_regval;
-	struct	{
-		uint64_t	i_rsvd_1		  :	54;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t	i_vld			  :	 1;
+	uint64_t ii_iprte6a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} ii_iprte6a_fld_s;
 } ii_iprte6a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte7a_u {
-        uint64_t       ii_iprte7a_regval;
-        struct  {
-                uint64_t       i_rsvd_1                  :     54;
-                uint64_t       i_widget                  :      4;
-                uint64_t       i_to_cnt                  :      5;
-                uint64_t       i_vld                     :      1;
-        } ii_iprtea7_fld_s;
+	uint64_t ii_iprte7a_regval;
+	struct {
+		uint64_t i_rsvd_1:54;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
+	} ii_iprtea7_fld_s;
 } ii_iprte7a_u_t;
 
-
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
-
 typedef union ii_iprte0b_u {
-	uint64_t	ii_iprte0b_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte0b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 	} ii_iprte0b_fld_s;
 } ii_iprte0b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte1b_u {
-	uint64_t	ii_iprte1b_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte1b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 	} ii_iprte1b_fld_s;
 } ii_iprte1b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte2b_u {
-	uint64_t	ii_iprte2b_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte2b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 	} ii_iprte2b_fld_s;
 } ii_iprte2b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte3b_u {
-	uint64_t	ii_iprte3b_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte3b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 	} ii_iprte3b_fld_s;
 } ii_iprte3b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte4b_u {
-	uint64_t	ii_iprte4b_regval;
-	struct	{
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte4b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 	} ii_iprte4b_fld_s;
 } ii_iprte4b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte5b_u {
-	uint64_t	ii_iprte5b_regval;
-	struct	{
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte5b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 	} ii_iprte5b_fld_s;
 } ii_iprte5b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte6b_u {
-	uint64_t	ii_iprte6b_regval;
-	struct	{
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
+	uint64_t ii_iprte6b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
 
 	} ii_iprte6b_fld_s;
 } ii_iprte6b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  There are 8 instances of this register. This register contains      *
  * the information that the II has to remember once it has launched a   *
  * PIO Read operation. The contents are used to form the correct        *
  * Router Network packet and direct the Crosstalk reply to the          *
  * appropriate processor.                                               *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iprte7b_u {
-        uint64_t       ii_iprte7b_regval;
-        struct  {
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_address		  :	47;
-		uint64_t	i_init			  :	 3;
-		uint64_t       i_source                  :     11;
-        } ii_iprte7b_fld_s;
+	uint64_t ii_iprte7b_regval;
+	struct {
+		uint64_t i_rsvd_1:3;
+		uint64_t i_address:47;
+		uint64_t i_init:3;
+		uint64_t i_source:11;
+	} ii_iprte7b_fld_s;
 } ii_iprte7b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  SHub II contains a feature which did not exist in      *
  * the Hub which automatically cleans up after a Read Response          *
  * timeout, including deallocation of the IPRTE and recovery of IBuf    *
@@ -2108,23 +2034,22 @@
  * Note that this register does not affect the contents of the IPRTE    *
  * registers. The Valid bits in those registers have to be              *
  * specifically turned off by software.                                 *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ipdr_u {
-	uint64_t	ii_ipdr_regval;
-	struct  {
-		uint64_t	i_te                      :	 3;
-		uint64_t	i_rsvd_1		  :	 1;
-		uint64_t	i_pnd			  :	 1;
-		uint64_t	i_init_rpcnt		  :	 1;
-		uint64_t	i_rsvd			  :	58;
+	uint64_t ii_ipdr_regval;
+	struct {
+		uint64_t i_te:3;
+		uint64_t i_rsvd_1:1;
+		uint64_t i_pnd:1;
+		uint64_t i_init_rpcnt:1;
+		uint64_t i_rsvd:58;
 	} ii_ipdr_fld_s;
 } ii_ipdr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  A write to this register causes a CRB entry to be returned to the   *
  * queue of free CRBs. The entry should have previously been cleared    *
  * (mark bit) via backdoor access to the pertinent CRB entry. This      *
@@ -2137,21 +2062,20 @@
  * software clears the mark bit, and finally 4) software writes to      *
  * the ICDR register to return the CRB entry to the list of free CRB    *
  * entries.                                                             *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icdr_u {
-	uint64_t	ii_icdr_regval;
-	struct  {
-		uint64_t	i_crb_num                 :	 4;
-		uint64_t	i_pnd			  :	 1;
-		uint64_t       i_rsvd                    :     59;
+	uint64_t ii_icdr_regval;
+	struct {
+		uint64_t i_crb_num:4;
+		uint64_t i_pnd:1;
+		uint64_t i_rsvd:59;
 	} ii_icdr_fld_s;
 } ii_icdr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register provides debug access to two FIFOs inside of II.      *
  * Both IOQ_MAX* fields of this register contain the instantaneous      *
  * depth (in units of the number of available entries) of the           *
@@ -2164,130 +2088,124 @@
  * this register is written. If there are any active entries in any     *
  * of these FIFOs when this register is written, the results are        *
  * undefined.                                                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ifdr_u {
-	uint64_t	ii_ifdr_regval;
-	struct  {
-		uint64_t	i_ioq_max_rq              :	 7;
-		uint64_t	i_set_ioq_rq		  :	 1;
-		uint64_t	i_ioq_max_rp		  :	 7;
-		uint64_t	i_set_ioq_rp		  :	 1;
-		uint64_t	i_rsvd			  :	48;
+	uint64_t ii_ifdr_regval;
+	struct {
+		uint64_t i_ioq_max_rq:7;
+		uint64_t i_set_ioq_rq:1;
+		uint64_t i_ioq_max_rp:7;
+		uint64_t i_set_ioq_rp:1;
+		uint64_t i_rsvd:48;
 	} ii_ifdr_fld_s;
 } ii_ifdr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register allows the II to become sluggish in removing          *
  * messages from its inbound queue (IIQ). This will cause messages to   *
  * back up in either virtual channel. Disabling the "molasses" mode     *
  * subsequently allows the II to be tested under stress. In the         *
  * sluggish ("Molasses") mode, the localized effects of congestion      *
  * can be observed.                                                     *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iiap_u {
-        uint64_t       ii_iiap_regval;
-        struct  {
-                uint64_t       i_rq_mls                  :      6;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_rp_mls		  :	 6;
-		uint64_t       i_rsvd                    :     50;
-        } ii_iiap_fld_s;
+	uint64_t ii_iiap_regval;
+	struct {
+		uint64_t i_rq_mls:6;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_rp_mls:6;
+		uint64_t i_rsvd:50;
+	} ii_iiap_fld_s;
 } ii_iiap_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register allows several parameters of CRB operation to be      *
  * set. Note that writing to this register can have catastrophic side   *
  * effects, if the CRB is not quiescent, i.e. if the CRB is             *
  * processing protocol messages when the write occurs.                  *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icmr_u {
-	uint64_t	ii_icmr_regval;
-	struct  {
-		uint64_t	i_sp_msg                  :	 1;
-		uint64_t	i_rd_hdr		  :	 1;
-		uint64_t	i_rsvd_4		  :	 2;
-		uint64_t	i_c_cnt			  :	 4;
-		uint64_t	i_rsvd_3		  :	 4;
-		uint64_t	i_clr_rqpd		  :	 1;
-		uint64_t	i_clr_rppd		  :	 1;
-		uint64_t	i_rsvd_2		  :	 2;
-		uint64_t	i_fc_cnt		  :	 4;
-		uint64_t	i_crb_vld		  :	15;
-		uint64_t	i_crb_mark		  :	15;
-		uint64_t	i_rsvd_1		  :	 2;
-		uint64_t	i_precise		  :	 1;
-		uint64_t	i_rsvd			  :	11;
+	uint64_t ii_icmr_regval;
+	struct {
+		uint64_t i_sp_msg:1;
+		uint64_t i_rd_hdr:1;
+		uint64_t i_rsvd_4:2;
+		uint64_t i_c_cnt:4;
+		uint64_t i_rsvd_3:4;
+		uint64_t i_clr_rqpd:1;
+		uint64_t i_clr_rppd:1;
+		uint64_t i_rsvd_2:2;
+		uint64_t i_fc_cnt:4;
+		uint64_t i_crb_vld:15;
+		uint64_t i_crb_mark:15;
+		uint64_t i_rsvd_1:2;
+		uint64_t i_precise:1;
+		uint64_t i_rsvd:11;
 	} ii_icmr_fld_s;
 } ii_icmr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register allows control of the table portion of the CRB        *
  * logic via software. Control operations from this register have       *
  * priority over all incoming Crosstalk or BTE requests.                *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_iccr_u {
-	uint64_t	ii_iccr_regval;
-	struct  {
-		uint64_t	i_crb_num                 :	 4;
-		uint64_t	i_rsvd_1		  :	 4;
-		uint64_t	i_cmd			  :	 8;
-		uint64_t	i_pending		  :	 1;
-		uint64_t	i_rsvd			  :	47;
+	uint64_t ii_iccr_regval;
+	struct {
+		uint64_t i_crb_num:4;
+		uint64_t i_rsvd_1:4;
+		uint64_t i_cmd:8;
+		uint64_t i_pending:1;
+		uint64_t i_rsvd:47;
 	} ii_iccr_fld_s;
 } ii_iccr_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register allows the maximum timeout value to be programmed.    *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icto_u {
-	uint64_t	ii_icto_regval;
-	struct  {
-		uint64_t	i_timeout                 :	 8;
-		uint64_t	i_rsvd			  :	56;
+	uint64_t ii_icto_regval;
+	struct {
+		uint64_t i_timeout:8;
+		uint64_t i_rsvd:56;
 	} ii_icto_fld_s;
 } ii_icto_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register allows the timeout prescalar to be programmed. An     *
  * internal counter is associated with this register. When the          *
  * internal counter reaches the value of the PRESCALE field, the        *
  * timer registers in all valid CRBs are incremented (CRBx_D[TIMEOUT]   *
  * field). The internal counter resets to zero, and then continues      *
  * counting.                                                            *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ictp_u {
-	uint64_t	ii_ictp_regval;
-	struct  {
-		uint64_t	i_prescale                :	24;
-		uint64_t	i_rsvd			  :	40;
+	uint64_t ii_ictp_regval;
+	struct {
+		uint64_t i_prescale:24;
+		uint64_t i_rsvd:40;
 	} ii_ictp_fld_s;
 } ii_ictp_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 15 CRB Entries (ICRB0 to ICRBE) that are     *
  * used for Crosstalk operations (both cacheline and partial            *
  * operations) or BTE/IO. Because the CRB entries are very wide, five   *
@@ -2306,243 +2224,234 @@
  * recovering any potential error state from before the reset).         *
  * The following four tables summarize the format for the four          *
  * registers that are used for each ICRB# Entry.                        *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icrb0_a_u {
-	uint64_t	ii_icrb0_a_regval;
-	struct  {
-		uint64_t	ia_iow                    :	 1;
-		uint64_t	ia_vld			  :	 1;
-		uint64_t	ia_addr			  :	47;
-		uint64_t	ia_tnum			  :	 5;
-		uint64_t	ia_sidn			  :	 4;
-		uint64_t       ia_rsvd                   :      6;
+	uint64_t ii_icrb0_a_regval;
+	struct {
+		uint64_t ia_iow:1;
+		uint64_t ia_vld:1;
+		uint64_t ia_addr:47;
+		uint64_t ia_tnum:5;
+		uint64_t ia_sidn:4;
+		uint64_t ia_rsvd:6;
 	} ii_icrb0_a_fld_s;
 } ii_icrb0_a_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 15 CRB Entries (ICRB0 to ICRBE) that are     *
  * used for Crosstalk operations (both cacheline and partial            *
  * operations) or BTE/IO. Because the CRB entries are very wide, five   *
  * registers (_A to _E) are required to read and write each entry.      *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icrb0_b_u {
-	uint64_t	ii_icrb0_b_regval;
-	struct	{
-		uint64_t	ib_xt_err		  :	 1;
-		uint64_t	ib_mark			  :	 1;
-		uint64_t	ib_ln_uce		  :	 1;
-		uint64_t	ib_errcode		  :	 3;
-		uint64_t	ib_error		  :	 1;
-		uint64_t	ib_stall__bte_1		  :	 1;
-		uint64_t	ib_stall__bte_0		  :	 1;
-		uint64_t	ib_stall__intr		  :	 1;
-		uint64_t	ib_stall_ib		  :	 1;
-		uint64_t	ib_intvn		  :	 1;
-		uint64_t	ib_wb			  :	 1;
-		uint64_t	ib_hold			  :	 1;
-		uint64_t	ib_ack			  :	 1;
-		uint64_t	ib_resp			  :	 1;
-		uint64_t	ib_ack_cnt		  :	11;
-		uint64_t	ib_rsvd			  :	 7;
-		uint64_t	ib_exc			  :	 5;
-		uint64_t	ib_init			  :	 3;
-		uint64_t	ib_imsg			  :	 8;
-		uint64_t	ib_imsgtype		  :	 2;
-		uint64_t	ib_use_old		  :	 1;
-		uint64_t	ib_rsvd_1		  :	11;
+	uint64_t ii_icrb0_b_regval;
+	struct {
+		uint64_t ib_xt_err:1;
+		uint64_t ib_mark:1;
+		uint64_t ib_ln_uce:1;
+		uint64_t ib_errcode:3;
+		uint64_t ib_error:1;
+		uint64_t ib_stall__bte_1:1;
+		uint64_t ib_stall__bte_0:1;
+		uint64_t ib_stall__intr:1;
+		uint64_t ib_stall_ib:1;
+		uint64_t ib_intvn:1;
+		uint64_t ib_wb:1;
+		uint64_t ib_hold:1;
+		uint64_t ib_ack:1;
+		uint64_t ib_resp:1;
+		uint64_t ib_ack_cnt:11;
+		uint64_t ib_rsvd:7;
+		uint64_t ib_exc:5;
+		uint64_t ib_init:3;
+		uint64_t ib_imsg:8;
+		uint64_t ib_imsgtype:2;
+		uint64_t ib_use_old:1;
+		uint64_t ib_rsvd_1:11;
 	} ii_icrb0_b_fld_s;
 } ii_icrb0_b_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 15 CRB Entries (ICRB0 to ICRBE) that are     *
  * used for Crosstalk operations (both cacheline and partial            *
  * operations) or BTE/IO. Because the CRB entries are very wide, five   *
  * registers (_A to _E) are required to read and write each entry.      *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icrb0_c_u {
-	uint64_t	ii_icrb0_c_regval;
-	struct	{
-		uint64_t	ic_source		  :	15;
-		uint64_t	ic_size			  :	 2;
-		uint64_t	ic_ct			  :	 1;
-		uint64_t	ic_bte_num		  :	 1;
-		uint64_t	ic_gbr			  :	 1;
-		uint64_t	ic_resprqd		  :	 1;
-		uint64_t	ic_bo			  :	 1;
-		uint64_t	ic_suppl		  :	15;
-		uint64_t	ic_rsvd			  :	27;
+	uint64_t ii_icrb0_c_regval;
+	struct {
+		uint64_t ic_source:15;
+		uint64_t ic_size:2;
+		uint64_t ic_ct:1;
+		uint64_t ic_bte_num:1;
+		uint64_t ic_gbr:1;
+		uint64_t ic_resprqd:1;
+		uint64_t ic_bo:1;
+		uint64_t ic_suppl:15;
+		uint64_t ic_rsvd:27;
 	} ii_icrb0_c_fld_s;
 } ii_icrb0_c_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 15 CRB Entries (ICRB0 to ICRBE) that are     *
  * used for Crosstalk operations (both cacheline and partial            *
  * operations) or BTE/IO. Because the CRB entries are very wide, five   *
  * registers (_A to _E) are required to read and write each entry.      *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icrb0_d_u {
-	uint64_t	ii_icrb0_d_regval;
-	struct  {
-		uint64_t	id_pa_be                  :	43;
-		uint64_t	id_bte_op		  :	 1;
-		uint64_t	id_pr_psc		  :	 4;
-		uint64_t	id_pr_cnt		  :	 4;
-		uint64_t	id_sleep		  :	 1;
-		uint64_t	id_rsvd			  :	11;
+	uint64_t ii_icrb0_d_regval;
+	struct {
+		uint64_t id_pa_be:43;
+		uint64_t id_bte_op:1;
+		uint64_t id_pr_psc:4;
+		uint64_t id_pr_cnt:4;
+		uint64_t id_sleep:1;
+		uint64_t id_rsvd:11;
 	} ii_icrb0_d_fld_s;
 } ii_icrb0_d_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  There are 15 CRB Entries (ICRB0 to ICRBE) that are     *
  * used for Crosstalk operations (both cacheline and partial            *
  * operations) or BTE/IO. Because the CRB entries are very wide, five   *
  * registers (_A to _E) are required to read and write each entry.      *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icrb0_e_u {
-	uint64_t	ii_icrb0_e_regval;
-	struct  {
-		uint64_t	ie_timeout                :	 8;
-		uint64_t	ie_context		  :	15;
-		uint64_t	ie_rsvd			  :	 1;
-		uint64_t	ie_tvld			  :	 1;
-		uint64_t	ie_cvld			  :	 1;
-		uint64_t	ie_rsvd_0		  :	38;
+	uint64_t ii_icrb0_e_regval;
+	struct {
+		uint64_t ie_timeout:8;
+		uint64_t ie_context:15;
+		uint64_t ie_rsvd:1;
+		uint64_t ie_tvld:1;
+		uint64_t ie_cvld:1;
+		uint64_t ie_rsvd_0:38;
 	} ii_icrb0_e_fld_s;
 } ii_icrb0_e_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the lower 64 bits of the header of the       *
  * spurious message captured by II. Valid when the SP_MSG bit in ICMR   *
  * register is set.                                                     *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icsml_u {
-	uint64_t	ii_icsml_regval;
-	struct  {
-		uint64_t	i_tt_addr                 :	47;
-		uint64_t	i_newsuppl_ex		  :	14;
-		uint64_t	i_reserved		  :	 2;
-		uint64_t       i_overflow                :      1;
+	uint64_t ii_icsml_regval;
+	struct {
+		uint64_t i_tt_addr:47;
+		uint64_t i_newsuppl_ex:14;
+		uint64_t i_reserved:2;
+		uint64_t i_overflow:1;
 	} ii_icsml_fld_s;
 } ii_icsml_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the middle 64 bits of the header of the      *
  * spurious message captured by II. Valid when the SP_MSG bit in ICMR   *
  * register is set.                                                     *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icsmm_u {
-	uint64_t	ii_icsmm_regval;
-	struct  {
-		uint64_t	i_tt_ack_cnt              :	11;
-		uint64_t	i_reserved		  :	53;
+	uint64_t ii_icsmm_regval;
+	struct {
+		uint64_t i_tt_ack_cnt:11;
+		uint64_t i_reserved:53;
 	} ii_icsmm_fld_s;
 } ii_icsmm_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the microscopic state, all the inputs to     *
  * the protocol table, captured with the spurious message. Valid when   *
  * the SP_MSG bit in the ICMR register is set.                          *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_icsmh_u {
-	uint64_t	ii_icsmh_regval;
-	struct  {
-		uint64_t	i_tt_vld                  :	 1;
-		uint64_t	i_xerr			  :	 1;
-		uint64_t	i_ft_cwact_o		  :	 1;
-		uint64_t	i_ft_wact_o		  :	 1;
-		uint64_t       i_ft_active_o             :      1;
-		uint64_t	i_sync			  :	 1;
-		uint64_t	i_mnusg			  :	 1;
-		uint64_t	i_mnusz			  :	 1;
-		uint64_t	i_plusz			  :	 1;
-		uint64_t	i_plusg			  :	 1;
-		uint64_t	i_tt_exc		  :	 5;
-		uint64_t	i_tt_wb			  :	 1;
-		uint64_t	i_tt_hold		  :	 1;
-		uint64_t	i_tt_ack		  :	 1;
-		uint64_t	i_tt_resp		  :	 1;
-		uint64_t	i_tt_intvn		  :	 1;
-		uint64_t	i_g_stall_bte1		  :	 1;
-		uint64_t	i_g_stall_bte0		  :	 1;
-		uint64_t	i_g_stall_il		  :	 1;
-		uint64_t	i_g_stall_ib		  :	 1;
-		uint64_t	i_tt_imsg		  :	 8;
-		uint64_t	i_tt_imsgtype		  :	 2;
-		uint64_t	i_tt_use_old		  :	 1;
-		uint64_t	i_tt_respreqd		  :	 1;
-		uint64_t	i_tt_bte_num		  :	 1;
-		uint64_t	i_cbn			  :	 1;
-		uint64_t	i_match			  :	 1;
-		uint64_t	i_rpcnt_lt_34		  :	 1;
-		uint64_t	i_rpcnt_ge_34		  :	 1;
-		uint64_t	i_rpcnt_lt_18		  :	 1;
-		uint64_t	i_rpcnt_ge_18		  :	 1;
-		uint64_t       i_rpcnt_lt_2              :      1;
-		uint64_t	i_rpcnt_ge_2		  :	 1;
-		uint64_t	i_rqcnt_lt_18		  :	 1;
-		uint64_t	i_rqcnt_ge_18		  :	 1;
-		uint64_t	i_rqcnt_lt_2		  :	 1;
-		uint64_t	i_rqcnt_ge_2		  :	 1;
-		uint64_t	i_tt_device		  :	 7;
-		uint64_t	i_tt_init		  :	 3;
-		uint64_t	i_reserved		  :	 5;
+	uint64_t ii_icsmh_regval;
+	struct {
+		uint64_t i_tt_vld:1;
+		uint64_t i_xerr:1;
+		uint64_t i_ft_cwact_o:1;
+		uint64_t i_ft_wact_o:1;
+		uint64_t i_ft_active_o:1;
+		uint64_t i_sync:1;
+		uint64_t i_mnusg:1;
+		uint64_t i_mnusz:1;
+		uint64_t i_plusz:1;
+		uint64_t i_plusg:1;
+		uint64_t i_tt_exc:5;
+		uint64_t i_tt_wb:1;
+		uint64_t i_tt_hold:1;
+		uint64_t i_tt_ack:1;
+		uint64_t i_tt_resp:1;
+		uint64_t i_tt_intvn:1;
+		uint64_t i_g_stall_bte1:1;
+		uint64_t i_g_stall_bte0:1;
+		uint64_t i_g_stall_il:1;
+		uint64_t i_g_stall_ib:1;
+		uint64_t i_tt_imsg:8;
+		uint64_t i_tt_imsgtype:2;
+		uint64_t i_tt_use_old:1;
+		uint64_t i_tt_respreqd:1;
+		uint64_t i_tt_bte_num:1;
+		uint64_t i_cbn:1;
+		uint64_t i_match:1;
+		uint64_t i_rpcnt_lt_34:1;
+		uint64_t i_rpcnt_ge_34:1;
+		uint64_t i_rpcnt_lt_18:1;
+		uint64_t i_rpcnt_ge_18:1;
+		uint64_t i_rpcnt_lt_2:1;
+		uint64_t i_rpcnt_ge_2:1;
+		uint64_t i_rqcnt_lt_18:1;
+		uint64_t i_rqcnt_ge_18:1;
+		uint64_t i_rqcnt_lt_2:1;
+		uint64_t i_rqcnt_ge_2:1;
+		uint64_t i_tt_device:7;
+		uint64_t i_tt_init:3;
+		uint64_t i_reserved:5;
 	} ii_icsmh_fld_s;
 } ii_icsmh_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  The Shub DEBUG unit provides a 3-bit selection signal to the        *
  * II core and a 3-bit selection signal to the fsbclk domain in the II  *
  * wrapper.                                                             *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_idbss_u {
-	uint64_t	ii_idbss_regval;
-	struct  {
-		uint64_t	i_iioclk_core_submenu     :	 3;
-		uint64_t	i_rsvd			  :	 5;
-		uint64_t	i_fsbclk_wrapper_submenu  :	 3;
-		uint64_t	i_rsvd_1		  :	 5;
-		uint64_t	i_iioclk_menu		  :	 5;
-		uint64_t	i_rsvd_2		  :	43;
+	uint64_t ii_idbss_regval;
+	struct {
+		uint64_t i_iioclk_core_submenu:3;
+		uint64_t i_rsvd:5;
+		uint64_t i_fsbclk_wrapper_submenu:3;
+		uint64_t i_rsvd_1:5;
+		uint64_t i_iioclk_menu:5;
+		uint64_t i_rsvd_2:43;
 	} ii_idbss_fld_s;
 } ii_idbss_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register is used to set up the length for a       *
  * transfer and then to monitor the progress of that transfer. This     *
  * register needs to be initialized before a transfer is started. A     *
@@ -2553,63 +2462,60 @@
  * transfer completes, hardware will clear the Busy bit. The length     *
  * field will also contain the number of cache lines left to be         *
  * transferred.                                                         *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibls0_u {
-	uint64_t	ii_ibls0_regval;
-	struct	{
-		uint64_t	i_length		  :	16;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_busy			  :	 1;
-		uint64_t       i_rsvd                    :     43;
+	uint64_t ii_ibls0_regval;
+	struct {
+		uint64_t i_length:16;
+		uint64_t i_error:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_busy:1;
+		uint64_t i_rsvd:43;
 	} ii_ibls0_fld_s;
 } ii_ibls0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register should be loaded before a transfer is started. The    *
  * address to be loaded in bits 39:0 is the 40-bit TRex+ physical       *
  * address as described in Section 1.3, Figure2 and Figure3. Since      *
  * the bottom 7 bits of the address are always taken to be zero, BTE    *
  * transfers are always cacheline-aligned.                              *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibsa0_u {
-	uint64_t	ii_ibsa0_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 7;
-		uint64_t	i_addr			  :	42;
-		uint64_t       i_rsvd                    :     15;
+	uint64_t ii_ibsa0_regval;
+	struct {
+		uint64_t i_rsvd_1:7;
+		uint64_t i_addr:42;
+		uint64_t i_rsvd:15;
 	} ii_ibsa0_fld_s;
 } ii_ibsa0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register should be loaded before a transfer is started. The    *
  * address to be loaded in bits 39:0 is the 40-bit TRex+ physical       *
  * address as described in Section 1.3, Figure2 and Figure3. Since      *
  * the bottom 7 bits of the address are always taken to be zero, BTE    *
  * transfers are always cacheline-aligned.                              *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibda0_u {
-	uint64_t	ii_ibda0_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 7;
-		uint64_t	i_addr			  :	42;
-		uint64_t	i_rsvd			  :	15;
+	uint64_t ii_ibda0_regval;
+	struct {
+		uint64_t i_rsvd_1:7;
+		uint64_t i_addr:42;
+		uint64_t i_rsvd:15;
 	} ii_ibda0_fld_s;
 } ii_ibda0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  Writing to this register sets up the attributes of the transfer     *
  * and initiates the transfer operation. Reading this register has      *
  * the side effect of terminating any transfer in progress. Note:       *
@@ -2617,61 +2523,58 @@
  * other BTE. If a BTE stream has to be stopped (due to error           *
  * handling for example), both BTE streams should be stopped and        *
  * their transfers discarded.                                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibct0_u {
-	uint64_t	ii_ibct0_regval;
-	struct  {
-		uint64_t	i_zerofill                :	 1;
-		uint64_t	i_rsvd_2		  :	 3;
-		uint64_t	i_notify		  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t       i_poison                  :      1;
-		uint64_t       i_rsvd                    :     55;
+	uint64_t ii_ibct0_regval;
+	struct {
+		uint64_t i_zerofill:1;
+		uint64_t i_rsvd_2:3;
+		uint64_t i_notify:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_poison:1;
+		uint64_t i_rsvd:55;
 	} ii_ibct0_fld_s;
 } ii_ibct0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the address to which the WINV is sent.       *
  * This address has to be cache line aligned.                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibna0_u {
-	uint64_t	ii_ibna0_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 7;
-		uint64_t	i_addr			  :	42;
-		uint64_t	i_rsvd			  :	15;
+	uint64_t ii_ibna0_regval;
+	struct {
+		uint64_t i_rsvd_1:7;
+		uint64_t i_addr:42;
+		uint64_t i_rsvd:15;
 	} ii_ibna0_fld_s;
 } ii_ibna0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the programmable level as well as the node   *
  * ID and PI unit of the processor to which the interrupt will be       *
- * sent.                                                                *
- *                                                                      *
+ * sent.								*
+ *									*
  ************************************************************************/
 
 typedef union ii_ibia0_u {
-	uint64_t	ii_ibia0_regval;
-	struct  {
-		uint64_t	i_rsvd_2                   :	 1;
-		uint64_t	i_node_id		  :	11;
-		uint64_t	i_rsvd_1		  :	 4;
-		uint64_t	i_level			  :	 7;
-		uint64_t       i_rsvd                    :     41;
+	uint64_t ii_ibia0_regval;
+	struct {
+		uint64_t i_rsvd_2:1;
+		uint64_t i_node_id:11;
+		uint64_t i_rsvd_1:4;
+		uint64_t i_level:7;
+		uint64_t i_rsvd:41;
 	} ii_ibia0_fld_s;
 } ii_ibia0_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  * Description:  This register is used to set up the length for a       *
  * transfer and then to monitor the progress of that transfer. This     *
  * register needs to be initialized before a transfer is started. A     *
@@ -2682,63 +2585,60 @@
  * transfer completes, hardware will clear the Busy bit. The length     *
  * field will also contain the number of cache lines left to be         *
  * transferred.                                                         *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibls1_u {
-	uint64_t	ii_ibls1_regval;
-	struct  {
-		uint64_t	i_length                  :	16;
-		uint64_t	i_error			  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_busy			  :	 1;
-		uint64_t       i_rsvd                    :     43;
+	uint64_t ii_ibls1_regval;
+	struct {
+		uint64_t i_length:16;
+		uint64_t i_error:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_busy:1;
+		uint64_t i_rsvd:43;
 	} ii_ibls1_fld_s;
 } ii_ibls1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register should be loaded before a transfer is started. The    *
  * address to be loaded in bits 39:0 is the 40-bit TRex+ physical       *
  * address as described in Section 1.3, Figure2 and Figure3. Since      *
  * the bottom 7 bits of the address are always taken to be zero, BTE    *
  * transfers are always cacheline-aligned.                              *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibsa1_u {
-	uint64_t	ii_ibsa1_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 7;
-		uint64_t	i_addr			  :	33;
-		uint64_t	i_rsvd			  :	24;
+	uint64_t ii_ibsa1_regval;
+	struct {
+		uint64_t i_rsvd_1:7;
+		uint64_t i_addr:33;
+		uint64_t i_rsvd:24;
 	} ii_ibsa1_fld_s;
 } ii_ibsa1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register should be loaded before a transfer is started. The    *
  * address to be loaded in bits 39:0 is the 40-bit TRex+ physical       *
  * address as described in Section 1.3, Figure2 and Figure3. Since      *
  * the bottom 7 bits of the address are always taken to be zero, BTE    *
  * transfers are always cacheline-aligned.                              *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibda1_u {
-	uint64_t	ii_ibda1_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 7;
-		uint64_t	i_addr			  :	33;
-		uint64_t	i_rsvd			  :	24;
+	uint64_t ii_ibda1_regval;
+	struct {
+		uint64_t i_rsvd_1:7;
+		uint64_t i_addr:33;
+		uint64_t i_rsvd:24;
 	} ii_ibda1_fld_s;
 } ii_ibda1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  Writing to this register sets up the attributes of the transfer     *
  * and initiates the transfer operation. Reading this register has      *
  * the side effect of terminating any transfer in progress. Note:       *
@@ -2746,61 +2646,58 @@
  * other BTE. If a BTE stream has to be stopped (due to error           *
  * handling for example), both BTE streams should be stopped and        *
  * their transfers discarded.                                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibct1_u {
-	uint64_t	ii_ibct1_regval;
-	struct  {
-		uint64_t	i_zerofill                :	 1;
-		uint64_t	i_rsvd_2		  :	 3;
-		uint64_t	i_notify		  :	 1;
-		uint64_t	i_rsvd_1		  :	 3;
-		uint64_t	i_poison		  :	 1;
-		uint64_t	i_rsvd			  :	55;
+	uint64_t ii_ibct1_regval;
+	struct {
+		uint64_t i_zerofill:1;
+		uint64_t i_rsvd_2:3;
+		uint64_t i_notify:1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_poison:1;
+		uint64_t i_rsvd:55;
 	} ii_ibct1_fld_s;
 } ii_ibct1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the address to which the WINV is sent.       *
  * This address has to be cache line aligned.                           *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ibna1_u {
-	uint64_t	ii_ibna1_regval;
-	struct  {
-		uint64_t	i_rsvd_1                  :	 7;
-		uint64_t	i_addr			  :	33;
-		uint64_t       i_rsvd                    :     24;
+	uint64_t ii_ibna1_regval;
+	struct {
+		uint64_t i_rsvd_1:7;
+		uint64_t i_addr:33;
+		uint64_t i_rsvd:24;
 	} ii_ibna1_fld_s;
 } ii_ibna1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register contains the programmable level as well as the node   *
  * ID and PI unit of the processor to which the interrupt will be       *
- * sent.                                                                *
- *                                                                      *
+ * sent.								*
+ *									*
  ************************************************************************/
 
 typedef union ii_ibia1_u {
-	uint64_t	ii_ibia1_regval;
-	struct  {
-		uint64_t	i_pi_id                   :	 1;
-		uint64_t	i_node_id		  :	 8;
-		uint64_t	i_rsvd_1		  :	 7;
-		uint64_t	i_level			  :	 7;
-		uint64_t	i_rsvd			  :	41;
+	uint64_t ii_ibia1_regval;
+	struct {
+		uint64_t i_pi_id:1;
+		uint64_t i_node_id:8;
+		uint64_t i_rsvd_1:7;
+		uint64_t i_level:7;
+		uint64_t i_rsvd:41;
 	} ii_ibia1_fld_s;
 } ii_ibia1_u_t;
 
-
 /************************************************************************
- *                                                                      *
+ *									*
  *  This register defines the resources that feed information into      *
  * the two performance counters located in the IO Performance           *
  * Profiling Register. There are 17 different quantities that can be    *
@@ -2811,133 +2708,129 @@
  * other is available from the other performance counter. Hence, the    *
  * II supports all 17*16=272 possible combinations of quantities to     *
  * measure.                                                             *
- *                                                                      *
+ *									*
  ************************************************************************/
 
 typedef union ii_ipcr_u {
-	uint64_t	ii_ipcr_regval;
-	struct  {
-		uint64_t	i_ippr0_c                 :	 4;
-		uint64_t	i_ippr1_c		  :	 4;
-		uint64_t	i_icct			  :	 8;
-		uint64_t       i_rsvd                    :     48;
+	uint64_t ii_ipcr_regval;
+	struct {
+		uint64_t i_ippr0_c:4;
+		uint64_t i_ippr1_c:4;
+		uint64_t i_icct:8;
+		uint64_t i_rsvd:48;
 	} ii_ipcr_fld_s;
 } ii_ipcr_u_t;
 
-
 /************************************************************************
- *                                                                      *
- *                                                                      *
- *                                                                      *
+ *									*
+ *									*
+ *									*
  ************************************************************************/
 
 typedef union ii_ippr_u {
-	uint64_t	ii_ippr_regval;
-	struct  {
-		uint64_t	i_ippr0                   :	32;
-		uint64_t	i_ippr1			  :	32;
+	uint64_t ii_ippr_regval;
+	struct {
+		uint64_t i_ippr0:32;
+		uint64_t i_ippr1:32;
 	} ii_ippr_fld_s;
 } ii_ippr_u_t;
 
-
-
-/**************************************************************************
- *                                                                        *
- * The following defines which were not formed into structures are        *
- * probably indentical to another register, and the name of the           *
- * register is provided against each of these registers. This             *
- * information needs to be checked carefully                              *
- *                                                                        *
- *           IIO_ICRB1_A                IIO_ICRB0_A                       *
- *           IIO_ICRB1_B                IIO_ICRB0_B                       *
- *           IIO_ICRB1_C                IIO_ICRB0_C                       *
- *           IIO_ICRB1_D                IIO_ICRB0_D                       *
- *           IIO_ICRB1_E                IIO_ICRB0_E                       *
- *           IIO_ICRB2_A                IIO_ICRB0_A                       *
- *           IIO_ICRB2_B                IIO_ICRB0_B                       *
- *           IIO_ICRB2_C                IIO_ICRB0_C                       *
- *           IIO_ICRB2_D                IIO_ICRB0_D                       *
- *           IIO_ICRB2_E                IIO_ICRB0_E                       *
- *           IIO_ICRB3_A                IIO_ICRB0_A                       *
- *           IIO_ICRB3_B                IIO_ICRB0_B                       *
- *           IIO_ICRB3_C                IIO_ICRB0_C                       *
- *           IIO_ICRB3_D                IIO_ICRB0_D                       *
- *           IIO_ICRB3_E                IIO_ICRB0_E                       *
- *           IIO_ICRB4_A                IIO_ICRB0_A                       *
- *           IIO_ICRB4_B                IIO_ICRB0_B                       *
- *           IIO_ICRB4_C                IIO_ICRB0_C                       *
- *           IIO_ICRB4_D                IIO_ICRB0_D                       *
- *           IIO_ICRB4_E                IIO_ICRB0_E                       *
- *           IIO_ICRB5_A                IIO_ICRB0_A                       *
- *           IIO_ICRB5_B                IIO_ICRB0_B                       *
- *           IIO_ICRB5_C                IIO_ICRB0_C                       *
- *           IIO_ICRB5_D                IIO_ICRB0_D                       *
- *           IIO_ICRB5_E                IIO_ICRB0_E                       *
- *           IIO_ICRB6_A                IIO_ICRB0_A                       *
- *           IIO_ICRB6_B                IIO_ICRB0_B                       *
- *           IIO_ICRB6_C                IIO_ICRB0_C                       *
- *           IIO_ICRB6_D                IIO_ICRB0_D                       *
- *           IIO_ICRB6_E                IIO_ICRB0_E                       *
- *           IIO_ICRB7_A                IIO_ICRB0_A                       *
- *           IIO_ICRB7_B                IIO_ICRB0_B                       *
- *           IIO_ICRB7_C                IIO_ICRB0_C                       *
- *           IIO_ICRB7_D                IIO_ICRB0_D                       *
- *           IIO_ICRB7_E                IIO_ICRB0_E                       *
- *           IIO_ICRB8_A                IIO_ICRB0_A                       *
- *           IIO_ICRB8_B                IIO_ICRB0_B                       *
- *           IIO_ICRB8_C                IIO_ICRB0_C                       *
- *           IIO_ICRB8_D                IIO_ICRB0_D                       *
- *           IIO_ICRB8_E                IIO_ICRB0_E                       *
- *           IIO_ICRB9_A                IIO_ICRB0_A                       *
- *           IIO_ICRB9_B                IIO_ICRB0_B                       *
- *           IIO_ICRB9_C                IIO_ICRB0_C                       *
- *           IIO_ICRB9_D                IIO_ICRB0_D                       *
- *           IIO_ICRB9_E                IIO_ICRB0_E                       *
- *           IIO_ICRBA_A                IIO_ICRB0_A                       *
- *           IIO_ICRBA_B                IIO_ICRB0_B                       *
- *           IIO_ICRBA_C                IIO_ICRB0_C                       *
- *           IIO_ICRBA_D                IIO_ICRB0_D                       *
- *           IIO_ICRBA_E                IIO_ICRB0_E                       *
- *           IIO_ICRBB_A                IIO_ICRB0_A                       *
- *           IIO_ICRBB_B                IIO_ICRB0_B                       *
- *           IIO_ICRBB_C                IIO_ICRB0_C                       *
- *           IIO_ICRBB_D                IIO_ICRB0_D                       *
- *           IIO_ICRBB_E                IIO_ICRB0_E                       *
- *           IIO_ICRBC_A                IIO_ICRB0_A                       *
- *           IIO_ICRBC_B                IIO_ICRB0_B                       *
- *           IIO_ICRBC_C                IIO_ICRB0_C                       *
- *           IIO_ICRBC_D                IIO_ICRB0_D                       *
- *           IIO_ICRBC_E                IIO_ICRB0_E                       *
- *           IIO_ICRBD_A                IIO_ICRB0_A                       *
- *           IIO_ICRBD_B                IIO_ICRB0_B                       *
- *           IIO_ICRBD_C                IIO_ICRB0_C                       *
- *           IIO_ICRBD_D                IIO_ICRB0_D                       *
- *           IIO_ICRBD_E                IIO_ICRB0_E                       *
- *           IIO_ICRBE_A                IIO_ICRB0_A                       *
- *           IIO_ICRBE_B                IIO_ICRB0_B                       *
- *           IIO_ICRBE_C                IIO_ICRB0_C                       *
- *           IIO_ICRBE_D                IIO_ICRB0_D                       *
- *           IIO_ICRBE_E                IIO_ICRB0_E                       *
- *                                                                        *
- **************************************************************************/
-
+/************************************************************************
+ *									*
+ * The following defines which were not formed into structures are	*
+ * probably indentical to another register, and the name of the		*
+ * register is provided against each of these registers. This		*
+ * information needs to be checked carefully				*
+ *									*
+ *		IIO_ICRB1_A		IIO_ICRB0_A			*
+ *		IIO_ICRB1_B		IIO_ICRB0_B			*
+ *		IIO_ICRB1_C		IIO_ICRB0_C			*
+ *		IIO_ICRB1_D		IIO_ICRB0_D			*
+ *		IIO_ICRB1_E		IIO_ICRB0_E			*
+ *		IIO_ICRB2_A		IIO_ICRB0_A			*
+ *		IIO_ICRB2_B		IIO_ICRB0_B			*
+ *		IIO_ICRB2_C		IIO_ICRB0_C			*
+ *		IIO_ICRB2_D		IIO_ICRB0_D			*
+ *		IIO_ICRB2_E		IIO_ICRB0_E			*
+ *		IIO_ICRB3_A		IIO_ICRB0_A			*
+ *		IIO_ICRB3_B		IIO_ICRB0_B			*
+ *		IIO_ICRB3_C		IIO_ICRB0_C			*
+ *		IIO_ICRB3_D		IIO_ICRB0_D			*
+ *		IIO_ICRB3_E		IIO_ICRB0_E			*
+ *		IIO_ICRB4_A		IIO_ICRB0_A			*
+ *		IIO_ICRB4_B		IIO_ICRB0_B			*
+ *		IIO_ICRB4_C		IIO_ICRB0_C			*
+ *		IIO_ICRB4_D		IIO_ICRB0_D			*
+ *		IIO_ICRB4_E		IIO_ICRB0_E			*
+ *		IIO_ICRB5_A		IIO_ICRB0_A			*
+ *		IIO_ICRB5_B		IIO_ICRB0_B			*
+ *		IIO_ICRB5_C		IIO_ICRB0_C			*
+ *		IIO_ICRB5_D		IIO_ICRB0_D			*
+ *		IIO_ICRB5_E		IIO_ICRB0_E			*
+ *		IIO_ICRB6_A		IIO_ICRB0_A			*
+ *		IIO_ICRB6_B		IIO_ICRB0_B			*
+ *		IIO_ICRB6_C		IIO_ICRB0_C			*
+ *		IIO_ICRB6_D		IIO_ICRB0_D			*
+ *		IIO_ICRB6_E		IIO_ICRB0_E			*
+ *		IIO_ICRB7_A		IIO_ICRB0_A			*
+ *		IIO_ICRB7_B		IIO_ICRB0_B			*
+ *		IIO_ICRB7_C		IIO_ICRB0_C			*
+ *		IIO_ICRB7_D		IIO_ICRB0_D			*
+ *		IIO_ICRB7_E		IIO_ICRB0_E			*
+ *		IIO_ICRB8_A		IIO_ICRB0_A			*
+ *		IIO_ICRB8_B		IIO_ICRB0_B			*
+ *		IIO_ICRB8_C		IIO_ICRB0_C			*
+ *		IIO_ICRB8_D		IIO_ICRB0_D			*
+ *		IIO_ICRB8_E		IIO_ICRB0_E			*
+ *		IIO_ICRB9_A		IIO_ICRB0_A			*
+ *		IIO_ICRB9_B		IIO_ICRB0_B			*
+ *		IIO_ICRB9_C		IIO_ICRB0_C			*
+ *		IIO_ICRB9_D		IIO_ICRB0_D			*
+ *		IIO_ICRB9_E		IIO_ICRB0_E			*
+ *		IIO_ICRBA_A		IIO_ICRB0_A			*
+ *		IIO_ICRBA_B		IIO_ICRB0_B			*
+ *		IIO_ICRBA_C		IIO_ICRB0_C			*
+ *		IIO_ICRBA_D		IIO_ICRB0_D			*
+ *		IIO_ICRBA_E		IIO_ICRB0_E			*
+ *		IIO_ICRBB_A		IIO_ICRB0_A			*
+ *		IIO_ICRBB_B		IIO_ICRB0_B			*
+ *		IIO_ICRBB_C		IIO_ICRB0_C			*
+ *		IIO_ICRBB_D		IIO_ICRB0_D			*
+ *		IIO_ICRBB_E		IIO_ICRB0_E			*
+ *		IIO_ICRBC_A		IIO_ICRB0_A			*
+ *		IIO_ICRBC_B		IIO_ICRB0_B			*
+ *		IIO_ICRBC_C		IIO_ICRB0_C			*
+ *		IIO_ICRBC_D		IIO_ICRB0_D			*
+ *		IIO_ICRBC_E		IIO_ICRB0_E			*
+ *		IIO_ICRBD_A		IIO_ICRB0_A			*
+ *		IIO_ICRBD_B		IIO_ICRB0_B			*
+ *		IIO_ICRBD_C		IIO_ICRB0_C			*
+ *		IIO_ICRBD_D		IIO_ICRB0_D			*
+ *		IIO_ICRBD_E		IIO_ICRB0_E			*
+ *		IIO_ICRBE_A		IIO_ICRB0_A			*
+ *		IIO_ICRBE_B		IIO_ICRB0_B			*
+ *		IIO_ICRBE_C		IIO_ICRB0_C			*
+ *		IIO_ICRBE_D		IIO_ICRB0_D			*
+ *		IIO_ICRBE_E		IIO_ICRB0_E			*
+ *									*
+ ************************************************************************/
 
 /*
  * Slightly friendlier names for some common registers.
  */
-#define IIO_WIDGET              IIO_WID      /* Widget identification */
-#define IIO_WIDGET_STAT         IIO_WSTAT    /* Widget status register */
-#define IIO_WIDGET_CTRL         IIO_WCR      /* Widget control register */
-#define IIO_PROTECT             IIO_ILAPR    /* IO interface protection */
-#define IIO_PROTECT_OVRRD       IIO_ILAPO    /* IO protect override */
-#define IIO_OUTWIDGET_ACCESS    IIO_IOWA     /* Outbound widget access */
-#define IIO_INWIDGET_ACCESS     IIO_IIWA     /* Inbound widget access */
-#define IIO_INDEV_ERR_MASK      IIO_IIDEM    /* Inbound device error mask */
-#define IIO_LLP_CSR             IIO_ILCSR    /* LLP control and status */
-#define IIO_LLP_LOG             IIO_ILLR     /* LLP log */
-#define IIO_XTALKCC_TOUT        IIO_IXCC     /* Xtalk credit count timeout*/
-#define IIO_XTALKTT_TOUT        IIO_IXTT     /* Xtalk tail timeout */
-#define IIO_IO_ERR_CLR          IIO_IECLR    /* IO error clear */
+#define IIO_WIDGET              IIO_WID		/* Widget identification */
+#define IIO_WIDGET_STAT         IIO_WSTAT	/* Widget status register */
+#define IIO_WIDGET_CTRL         IIO_WCR		/* Widget control register */
+#define IIO_PROTECT             IIO_ILAPR	/* IO interface protection */
+#define IIO_PROTECT_OVRRD       IIO_ILAPO	/* IO protect override */
+#define IIO_OUTWIDGET_ACCESS    IIO_IOWA	/* Outbound widget access */
+#define IIO_INWIDGET_ACCESS     IIO_IIWA	/* Inbound widget access */
+#define IIO_INDEV_ERR_MASK      IIO_IIDEM	/* Inbound device error mask */
+#define IIO_LLP_CSR             IIO_ILCSR	/* LLP control and status */
+#define IIO_LLP_LOG             IIO_ILLR	/* LLP log */
+#define IIO_XTALKCC_TOUT        IIO_IXCC	/* Xtalk credit count timeout */
+#define IIO_XTALKTT_TOUT        IIO_IXTT	/* Xtalk tail timeout */
+#define IIO_IO_ERR_CLR          IIO_IECLR	/* IO error clear */
 #define IIO_IGFX_0 		IIO_IGFX0
 #define IIO_IGFX_1 		IIO_IGFX1
 #define IIO_IBCT_0		IIO_IBCT0
@@ -2957,12 +2850,12 @@
 #define IIO_PRTE_A(_x)		(IIO_IPRTE0_A + (8 * (_x)))
 #define IIO_PRTE_B(_x)		(IIO_IPRTE0_B + (8 * (_x)))
 #define IIO_NUM_PRTES		8	/* Total number of PRB table entries */
-#define IIO_WIDPRTE_A(x)	IIO_PRTE_A(((x) - 8)) /* widget ID to its PRTE num */
-#define IIO_WIDPRTE_B(x)	IIO_PRTE_B(((x) - 8)) /* widget ID to its PRTE num */
+#define IIO_WIDPRTE_A(x)	IIO_PRTE_A(((x) - 8))	/* widget ID to its PRTE num */
+#define IIO_WIDPRTE_B(x)	IIO_PRTE_B(((x) - 8))	/* widget ID to its PRTE num */
 
-#define IIO_NUM_IPRBS 		(9) 
+#define IIO_NUM_IPRBS 		9
 
-#define IIO_LLP_CSR_IS_UP               0x00002000
+#define IIO_LLP_CSR_IS_UP		0x00002000
 #define IIO_LLP_CSR_LLP_STAT_MASK       0x00003000
 #define IIO_LLP_CSR_LLP_STAT_SHFT       12
 
@@ -2970,30 +2863,29 @@
 #define IIO_LLP_SN_MAX  0xffff	/* in ILLR SN_CNT, Max Sequence Number errors */
 
 /* key to IIO_PROTECT_OVRRD */
-#define IIO_PROTECT_OVRRD_KEY   0x53474972756c6573ull   /* "SGIrules" */
+#define IIO_PROTECT_OVRRD_KEY   0x53474972756c6573ull	/* "SGIrules" */
 
 /* BTE register names */
-#define IIO_BTE_STAT_0          IIO_IBLS_0   /* Also BTE length/status 0 */
-#define IIO_BTE_SRC_0           IIO_IBSA_0   /* Also BTE source address  0 */
-#define IIO_BTE_DEST_0          IIO_IBDA_0   /* Also BTE dest. address 0 */
-#define IIO_BTE_CTRL_0          IIO_IBCT_0   /* Also BTE control/terminate 0 */
-#define IIO_BTE_NOTIFY_0        IIO_IBNA_0   /* Also BTE notification 0 */
-#define IIO_BTE_INT_0           IIO_IBIA_0   /* Also BTE interrupt 0 */
-#define IIO_BTE_OFF_0           0            /* Base offset from BTE 0 regs. */
-#define IIO_BTE_OFF_1   	(IIO_IBLS_1 - IIO_IBLS_0) /* Offset from base to BTE 1 */
+#define IIO_BTE_STAT_0          IIO_IBLS_0	/* Also BTE length/status 0 */
+#define IIO_BTE_SRC_0           IIO_IBSA_0	/* Also BTE source address  0 */
+#define IIO_BTE_DEST_0          IIO_IBDA_0	/* Also BTE dest. address 0 */
+#define IIO_BTE_CTRL_0          IIO_IBCT_0	/* Also BTE control/terminate 0 */
+#define IIO_BTE_NOTIFY_0        IIO_IBNA_0	/* Also BTE notification 0 */
+#define IIO_BTE_INT_0           IIO_IBIA_0	/* Also BTE interrupt 0 */
+#define IIO_BTE_OFF_0           0	/* Base offset from BTE 0 regs. */
+#define IIO_BTE_OFF_1   	(IIO_IBLS_1 - IIO_IBLS_0)	/* Offset from base to BTE 1 */
 
 /* BTE register offsets from base */
 #define BTEOFF_STAT             0
-#define BTEOFF_SRC              (IIO_BTE_SRC_0 - IIO_BTE_STAT_0)
-#define BTEOFF_DEST             (IIO_BTE_DEST_0 - IIO_BTE_STAT_0)
-#define BTEOFF_CTRL             (IIO_BTE_CTRL_0 - IIO_BTE_STAT_0)
-#define BTEOFF_NOTIFY           (IIO_BTE_NOTIFY_0 - IIO_BTE_STAT_0)
-#define BTEOFF_INT              (IIO_BTE_INT_0 - IIO_BTE_STAT_0)
-
+#define BTEOFF_SRC      	(IIO_BTE_SRC_0 - IIO_BTE_STAT_0)
+#define BTEOFF_DEST     	(IIO_BTE_DEST_0 - IIO_BTE_STAT_0)
+#define BTEOFF_CTRL     	(IIO_BTE_CTRL_0 - IIO_BTE_STAT_0)
+#define BTEOFF_NOTIFY   	(IIO_BTE_NOTIFY_0 - IIO_BTE_STAT_0)
+#define BTEOFF_INT      	(IIO_BTE_INT_0 - IIO_BTE_STAT_0)
 
 /* names used in shub diags */
-#define IIO_BASE_BTE0   IIO_IBLS_0		
-#define IIO_BASE_BTE1   IIO_IBLS_1		
+#define IIO_BASE_BTE0   IIO_IBLS_0
+#define IIO_BASE_BTE1   IIO_IBLS_1
 
 /*
  * Macro which takes the widget number, and returns the
@@ -3001,10 +2893,9 @@
  * value _x is expected to be a widget number in the range
  * 0, 8 - 0xF
  */
-#define IIO_IOPRB(_x)   (IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \
-                        (_x) : \
-                        (_x) - (HUB_WIDGET_ID_MIN-1)) << 3) )
-
+#define IIO_IOPRB(_x)	(IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \
+                	(_x) : \
+                	(_x) - (HUB_WIDGET_ID_MIN-1)) << 3) )
 
 /* GFX Flow Control Node/Widget Register */
 #define IIO_IGFX_W_NUM_BITS	4	/* size of widget num field */
@@ -3025,7 +2916,6 @@
 	(((node)   & IIO_IGFX_N_NUM_MASK) << IIO_IGFX_N_NUM_SHIFT) |	 \
 	(((cpu)    & IIO_IGFX_P_NUM_MASK) << IIO_IGFX_P_NUM_SHIFT))
 
-
 /* Scratch registers (all bits available) */
 #define IIO_SCRATCH_REG0        IIO_ISCR0
 #define IIO_SCRATCH_REG1        IIO_ISCR1
@@ -3046,21 +2936,21 @@
 #define IIO_SCRATCH_BIT1_0      0x0000000000000001UL
 #define IIO_SCRATCH_BIT1_1      0x0000000000000002UL
 /* IO Translation Table Entries */
-#define IIO_NUM_ITTES   7               /* ITTEs numbered 0..6 */
-                                        /* Hw manuals number them 1..7! */
+#define IIO_NUM_ITTES   7	/* ITTEs numbered 0..6 */
+					/* Hw manuals number them 1..7! */
 /*
  * IIO_IMEM Register fields.
  */
-#define IIO_IMEM_W0ESD  0x1UL             /* Widget 0 shut down due to error */
-#define IIO_IMEM_B0ESD  (1UL << 4)        /* BTE 0 shut down due to error */
-#define IIO_IMEM_B1ESD  (1UL << 8)        /* BTE 1 Shut down due to error */
+#define IIO_IMEM_W0ESD  0x1UL	/* Widget 0 shut down due to error */
+#define IIO_IMEM_B0ESD	(1UL << 4)	/* BTE 0 shut down due to error */
+#define IIO_IMEM_B1ESD	(1UL << 8)	/* BTE 1 Shut down due to error */
 
 /*
  * As a permanent workaround for a bug in the PI side of the shub, we've
  * redefined big window 7 as small window 0.
  XXX does this still apply for SN1??
  */
-#define HUB_NUM_BIG_WINDOW      (IIO_NUM_ITTES - 1)
+#define HUB_NUM_BIG_WINDOW	(IIO_NUM_ITTES - 1)
 
 /*
  * Use the top big window as a surrogate for the first small window
@@ -3071,11 +2961,11 @@
 
 /*
  * CRB manipulation macros
- *      The CRB macros are slightly complicated, since there are up to
- *      four registers associated with each CRB entry.
+ *	The CRB macros are slightly complicated, since there are up to
+ *	four registers associated with each CRB entry.
  */
-#define IIO_NUM_CRBS            15      /* Number of CRBs */
-#define IIO_NUM_PC_CRBS         4       /* Number of partial cache CRBs */
+#define IIO_NUM_CRBS            15	/* Number of CRBs */
+#define IIO_NUM_PC_CRBS         4	/* Number of partial cache CRBs */
 #define IIO_ICRB_OFFSET         8
 #define IIO_ICRB_0              IIO_ICRB0_A
 #define IIO_ICRB_ADDR_SHFT	2	/* Shift to get proper address */
@@ -3083,43 +2973,43 @@
         #define IIO_FIRST_PC_ENTRY 12
  */
 
-#define IIO_ICRB_A(_x)  ((u64)(IIO_ICRB_0 + (6 * IIO_ICRB_OFFSET * (_x))))
-#define IIO_ICRB_B(_x)  ((u64)((char *)IIO_ICRB_A(_x) + 1*IIO_ICRB_OFFSET))
-#define IIO_ICRB_C(_x)  ((u64)((char *)IIO_ICRB_A(_x) + 2*IIO_ICRB_OFFSET))
-#define IIO_ICRB_D(_x)  ((u64)((char *)IIO_ICRB_A(_x) + 3*IIO_ICRB_OFFSET))
-#define IIO_ICRB_E(_x)  ((u64)((char *)IIO_ICRB_A(_x) + 4*IIO_ICRB_OFFSET))
+#define IIO_ICRB_A(_x)	((u64)(IIO_ICRB_0 + (6 * IIO_ICRB_OFFSET * (_x))))
+#define IIO_ICRB_B(_x)	((u64)((char *)IIO_ICRB_A(_x) + 1*IIO_ICRB_OFFSET))
+#define IIO_ICRB_C(_x)	((u64)((char *)IIO_ICRB_A(_x) + 2*IIO_ICRB_OFFSET))
+#define IIO_ICRB_D(_x)	((u64)((char *)IIO_ICRB_A(_x) + 3*IIO_ICRB_OFFSET))
+#define IIO_ICRB_E(_x)	((u64)((char *)IIO_ICRB_A(_x) + 4*IIO_ICRB_OFFSET))
 
 #define TNUM_TO_WIDGET_DEV(_tnum)	(_tnum & 0x7)
 
 /*
  * values for "ecode" field
  */
-#define IIO_ICRB_ECODE_DERR     0       /* Directory error due to IIO access */
-#define IIO_ICRB_ECODE_PERR     1       /* Poison error on IO access */
-#define IIO_ICRB_ECODE_WERR     2       /* Write error by IIO access
-                                         * e.g. WINV to a Read only line. */
-#define IIO_ICRB_ECODE_AERR     3       /* Access error caused by IIO access */
-#define IIO_ICRB_ECODE_PWERR    4       /* Error on partial write       */
-#define IIO_ICRB_ECODE_PRERR    5       /* Error on partial read        */
-#define IIO_ICRB_ECODE_TOUT     6       /* CRB timeout before deallocating */
-#define IIO_ICRB_ECODE_XTERR    7       /* Incoming xtalk pkt had error bit */
+#define IIO_ICRB_ECODE_DERR     0	/* Directory error due to IIO access */
+#define IIO_ICRB_ECODE_PERR     1	/* Poison error on IO access */
+#define IIO_ICRB_ECODE_WERR     2	/* Write error by IIO access
+					 * e.g. WINV to a Read only line. */
+#define IIO_ICRB_ECODE_AERR     3	/* Access error caused by IIO access */
+#define IIO_ICRB_ECODE_PWERR    4	/* Error on partial write */
+#define IIO_ICRB_ECODE_PRERR    5	/* Error on partial read  */
+#define IIO_ICRB_ECODE_TOUT     6	/* CRB timeout before deallocating */
+#define IIO_ICRB_ECODE_XTERR    7	/* Incoming xtalk pkt had error bit */
 
 /*
  * Values for field imsgtype
  */
-#define IIO_ICRB_IMSGT_XTALK    0       /* Incoming Meessage from Xtalk */
-#define IIO_ICRB_IMSGT_BTE      1       /* Incoming message from BTE    */
-#define IIO_ICRB_IMSGT_SN1NET   2       /* Incoming message from SN1 net */
-#define IIO_ICRB_IMSGT_CRB      3       /* Incoming message from CRB ???  */
+#define IIO_ICRB_IMSGT_XTALK    0	/* Incoming Meessage from Xtalk */
+#define IIO_ICRB_IMSGT_BTE      1	/* Incoming message from BTE    */
+#define IIO_ICRB_IMSGT_SN1NET   2	/* Incoming message from SN1 net */
+#define IIO_ICRB_IMSGT_CRB      3	/* Incoming message from CRB ???  */
 
 /*
  * values for field initiator.
  */
-#define IIO_ICRB_INIT_XTALK     0       /* Message originated in xtalk  */
-#define IIO_ICRB_INIT_BTE0      0x1     /* Message originated in BTE 0  */
-#define IIO_ICRB_INIT_SN1NET    0x2     /* Message originated in SN1net */
-#define IIO_ICRB_INIT_CRB       0x3     /* Message originated in CRB ?  */
-#define IIO_ICRB_INIT_BTE1      0x5     /* MEssage originated in BTE 1  */
+#define IIO_ICRB_INIT_XTALK     0	/* Message originated in xtalk  */
+#define IIO_ICRB_INIT_BTE0      0x1	/* Message originated in BTE 0  */
+#define IIO_ICRB_INIT_SN1NET    0x2	/* Message originated in SN1net */
+#define IIO_ICRB_INIT_CRB       0x3	/* Message originated in CRB ?  */
+#define IIO_ICRB_INIT_BTE1      0x5	/* MEssage originated in BTE 1  */
 
 /*
  * Number of credits Hub widget has while sending req/response to
@@ -3127,8 +3017,8 @@
  * Value of 3 is required by Xbow 1.1
  * We may be able to increase this to 4 with Xbow 1.2.
  */
-#define       HUBII_XBOW_CREDIT       3
-#define       HUBII_XBOW_REV2_CREDIT  4
+#define		   HUBII_XBOW_CREDIT       3
+#define		   HUBII_XBOW_REV2_CREDIT  4
 
 /*
  * Number of credits that xtalk devices should use when communicating
@@ -3159,28 +3049,28 @@
  */
 
 #define IIO_ICMR_CRB_VLD_SHFT   20
-#define IIO_ICMR_CRB_VLD_MASK   (0x7fffUL << IIO_ICMR_CRB_VLD_SHFT)
+#define IIO_ICMR_CRB_VLD_MASK	(0x7fffUL << IIO_ICMR_CRB_VLD_SHFT)
 
 #define IIO_ICMR_FC_CNT_SHFT    16
-#define IIO_ICMR_FC_CNT_MASK    (0xf << IIO_ICMR_FC_CNT_SHFT)
+#define IIO_ICMR_FC_CNT_MASK	(0xf << IIO_ICMR_FC_CNT_SHFT)
 
 #define IIO_ICMR_C_CNT_SHFT     4
-#define IIO_ICMR_C_CNT_MASK     (0xf << IIO_ICMR_C_CNT_SHFT)
+#define IIO_ICMR_C_CNT_MASK	(0xf << IIO_ICMR_C_CNT_SHFT)
 
-#define IIO_ICMR_PRECISE        (1UL << 52)
-#define IIO_ICMR_CLR_RPPD       (1UL << 13)
-#define IIO_ICMR_CLR_RQPD       (1UL << 12)
+#define IIO_ICMR_PRECISE	(1UL << 52)
+#define IIO_ICMR_CLR_RPPD	(1UL << 13)
+#define IIO_ICMR_CLR_RQPD	(1UL << 12)
 
 /*
  * IIO PIO Deallocation register field masks : (IIO_IPDR)
  XXX present but not needed in bedrock?  See the manual.
  */
-#define IIO_IPDR_PND    (1 << 4)
+#define IIO_IPDR_PND    	(1 << 4)
 
 /*
  * IIO CRB deallocation register field masks: (IIO_ICDR)
  */
-#define IIO_ICDR_PND    (1 << 4)
+#define IIO_ICDR_PND    	(1 << 4)
 
 /* 
  * IO BTE Length/Status (IIO_IBLS) register bit field definitions
@@ -3223,35 +3113,35 @@
 /*
  * IO Error Clear register bit field definitions
  */
-#define IECLR_PI1_FWD_INT	(1UL << 31)  /* clear PI1_FORWARD_INT in iidsr */
-#define IECLR_PI0_FWD_INT	(1UL << 30)  /* clear PI0_FORWARD_INT in iidsr */
-#define IECLR_SPUR_RD_HDR	(1UL << 29)  /* clear valid bit in ixss reg */
-#define IECLR_BTE1		(1UL << 18)  /* clear bte error 1 */
-#define IECLR_BTE0		(1UL << 17)  /* clear bte error 0 */
-#define IECLR_CRAZY		(1UL << 16)  /* clear crazy bit in wstat reg */
-#define IECLR_PRB_F		(1UL << 15)  /* clear err bit in PRB_F reg */
-#define IECLR_PRB_E		(1UL << 14)  /* clear err bit in PRB_E reg */
-#define IECLR_PRB_D		(1UL << 13)  /* clear err bit in PRB_D reg */
-#define IECLR_PRB_C		(1UL << 12)  /* clear err bit in PRB_C reg */
-#define IECLR_PRB_B		(1UL << 11)  /* clear err bit in PRB_B reg */
-#define IECLR_PRB_A		(1UL << 10)  /* clear err bit in PRB_A reg */
-#define IECLR_PRB_9		(1UL << 9)   /* clear err bit in PRB_9 reg */
-#define IECLR_PRB_8		(1UL << 8)   /* clear err bit in PRB_8 reg */
-#define IECLR_PRB_0		(1UL << 0)   /* clear err bit in PRB_0 reg */
+#define IECLR_PI1_FWD_INT	(1UL << 31)	/* clear PI1_FORWARD_INT in iidsr */
+#define IECLR_PI0_FWD_INT	(1UL << 30)	/* clear PI0_FORWARD_INT in iidsr */
+#define IECLR_SPUR_RD_HDR	(1UL << 29)	/* clear valid bit in ixss reg */
+#define IECLR_BTE1		(1UL << 18)	/* clear bte error 1 */
+#define IECLR_BTE0		(1UL << 17)	/* clear bte error 0 */
+#define IECLR_CRAZY		(1UL << 16)	/* clear crazy bit in wstat reg */
+#define IECLR_PRB_F		(1UL << 15)	/* clear err bit in PRB_F reg */
+#define IECLR_PRB_E		(1UL << 14)	/* clear err bit in PRB_E reg */
+#define IECLR_PRB_D		(1UL << 13)	/* clear err bit in PRB_D reg */
+#define IECLR_PRB_C		(1UL << 12)	/* clear err bit in PRB_C reg */
+#define IECLR_PRB_B		(1UL << 11)	/* clear err bit in PRB_B reg */
+#define IECLR_PRB_A		(1UL << 10)	/* clear err bit in PRB_A reg */
+#define IECLR_PRB_9		(1UL << 9)	/* clear err bit in PRB_9 reg */
+#define IECLR_PRB_8		(1UL << 8)	/* clear err bit in PRB_8 reg */
+#define IECLR_PRB_0		(1UL << 0)	/* clear err bit in PRB_0 reg */
 
 /*
  * IIO CRB control register Fields: IIO_ICCR 
  */
-#define	IIO_ICCR_PENDING	(0x10000)
-#define	IIO_ICCR_CMD_MASK	(0xFF)
-#define	IIO_ICCR_CMD_SHFT	(7)
-#define	IIO_ICCR_CMD_NOP	(0x0)	/* No Op */
-#define	IIO_ICCR_CMD_WAKE	(0x100) /* Reactivate CRB entry and process */
-#define	IIO_ICCR_CMD_TIMEOUT	(0x200)	/* Make CRB timeout & mark invalid */
-#define	IIO_ICCR_CMD_EJECT	(0x400)	/* Contents of entry written to memory 
+#define	IIO_ICCR_PENDING	0x10000
+#define	IIO_ICCR_CMD_MASK	0xFF
+#define	IIO_ICCR_CMD_SHFT	7
+#define	IIO_ICCR_CMD_NOP	0x0	/* No Op */
+#define	IIO_ICCR_CMD_WAKE	0x100	/* Reactivate CRB entry and process */
+#define	IIO_ICCR_CMD_TIMEOUT	0x200	/* Make CRB timeout & mark invalid */
+#define	IIO_ICCR_CMD_EJECT	0x400	/* Contents of entry written to memory
 					 * via a WB
 					 */
-#define	IIO_ICCR_CMD_FLUSH	(0x800)
+#define	IIO_ICCR_CMD_FLUSH	0x800
 
 /*
  *
@@ -3283,8 +3173,8 @@
  * Easy access macros for CRBs, all 5 registers (A-E)
  */
 typedef ii_icrb0_a_u_t icrba_t;
-#define a_sidn          ii_icrb0_a_fld_s.ia_sidn
-#define a_tnum          ii_icrb0_a_fld_s.ia_tnum
+#define a_sidn		ii_icrb0_a_fld_s.ia_sidn
+#define a_tnum		ii_icrb0_a_fld_s.ia_tnum
 #define a_addr          ii_icrb0_a_fld_s.ia_addr
 #define a_valid         ii_icrb0_a_fld_s.ia_vld
 #define a_iow           ii_icrb0_a_fld_s.ia_iow
@@ -3324,14 +3214,13 @@
 #define c_source        ii_icrb0_c_fld_s.ic_source
 #define c_regvalue	ii_icrb0_c_regval
 
-
 typedef ii_icrb0_d_u_t icrbd_t;
 #define d_sleep         ii_icrb0_d_fld_s.id_sleep
 #define d_pricnt        ii_icrb0_d_fld_s.id_pr_cnt
 #define d_pripsc        ii_icrb0_d_fld_s.id_pr_psc
 #define d_bteop         ii_icrb0_d_fld_s.id_bte_op
-#define d_bteaddr       ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names*/
-#define d_benable       ii_icrb0_d_fld_s.id_pa_be /* ic_pa_be fld has 2 names*/
+#define d_bteaddr       ii_icrb0_d_fld_s.id_pa_be	/* ic_pa_be fld has 2 names */
+#define d_benable       ii_icrb0_d_fld_s.id_pa_be	/* ic_pa_be fld has 2 names */
 #define d_regvalue	ii_icrb0_d_regval
 
 typedef ii_icrb0_e_u_t icrbe_t;
@@ -3341,7 +3230,6 @@
 #define icrbe_timeout   ii_icrb0_e_fld_s.ie_timeout
 #define e_regvalue	ii_icrb0_e_regval
 
-
 /* Number of widgets supported by shub */
 #define HUB_NUM_WIDGET          9
 #define HUB_WIDGET_ID_MIN       0x8
@@ -3367,27 +3255,27 @@
 
 #define LNK_STAT_WORKING        0x2		/* LLP is working */
 
-#define IIO_WSTAT_ECRAZY        (1ULL << 32)    /* Hub gone crazy */
-#define IIO_WSTAT_TXRETRY       (1ULL << 9)     /* Hub Tx Retry timeout */
-#define IIO_WSTAT_TXRETRY_MASK  (0x7F)   /* should be 0xFF?? */
-#define IIO_WSTAT_TXRETRY_SHFT  (16)
-#define IIO_WSTAT_TXRETRY_CNT(w)        (((w) >> IIO_WSTAT_TXRETRY_SHFT) & \
-                                          IIO_WSTAT_TXRETRY_MASK)
+#define IIO_WSTAT_ECRAZY	(1ULL << 32)	/* Hub gone crazy */
+#define IIO_WSTAT_TXRETRY	(1ULL << 9)	/* Hub Tx Retry timeout */
+#define IIO_WSTAT_TXRETRY_MASK  0x7F		/* should be 0xFF?? */
+#define IIO_WSTAT_TXRETRY_SHFT  16
+#define IIO_WSTAT_TXRETRY_CNT(w)	(((w) >> IIO_WSTAT_TXRETRY_SHFT) & \
+                          		IIO_WSTAT_TXRETRY_MASK)
 
 /* Number of II perf. counters we can multiplex at once */
 
 #define IO_PERF_SETS	32
 
 /* Bit for the widget in inbound access register */
-#define IIO_IIWA_WIDGET(_w)     ((uint64_t)(1ULL << _w))
+#define IIO_IIWA_WIDGET(_w)	((uint64_t)(1ULL << _w))
 /* Bit for the widget in outbound access register */
-#define IIO_IOWA_WIDGET(_w)     ((uint64_t)(1ULL << _w))
+#define IIO_IOWA_WIDGET(_w)	((uint64_t)(1ULL << _w))
 
 /* NOTE: The following define assumes that we are going to get
  * widget numbers from 8 thru F and the device numbers within
  * widget from 0 thru 7.
  */
-#define IIO_IIDEM_WIDGETDEV_MASK(w, d)  ((uint64_t)(1ULL << (8 * ((w) - 8) + (d))))
+#define IIO_IIDEM_WIDGETDEV_MASK(w, d)	((uint64_t)(1ULL << (8 * ((w) - 8) + (d))))
 
 /* IO Interrupt Destination Register */
 #define IIO_IIDSR_SENT_SHIFT    28
@@ -3402,11 +3290,11 @@
 #define IIO_IIDSR_LVL_MASK      0x000000ff
 
 /* Xtalk timeout threshhold register (IIO_IXTT) */
-#define IXTT_RRSP_TO_SHFT	55	   /* read response timeout */
+#define IXTT_RRSP_TO_SHFT	55	/* read response timeout */
 #define IXTT_RRSP_TO_MASK	(0x1FULL << IXTT_RRSP_TO_SHFT)
-#define IXTT_RRSP_PS_SHFT	32	   /* read responsed TO prescalar */
+#define IXTT_RRSP_PS_SHFT	32	/* read responsed TO prescalar */
 #define IXTT_RRSP_PS_MASK	(0x7FFFFFULL << IXTT_RRSP_PS_SHFT)
-#define IXTT_TAIL_TO_SHFT	0	   /* tail timeout counter threshold */
+#define IXTT_TAIL_TO_SHFT	0	/* tail timeout counter threshold */
 #define IXTT_TAIL_TO_MASK	(0x3FFFFFFULL << IXTT_TAIL_TO_SHFT)
 
 /*
@@ -3414,17 +3302,17 @@
  */
 
 typedef union hubii_wcr_u {
-        uint64_t      wcr_reg_value;
-        struct {
-	  uint64_t	wcr_widget_id:   4,     /* LLP crossbar credit */
-			wcr_tag_mode:	 1,	/* Tag mode */
-			wcr_rsvd1:	 8,	/* Reserved */
-			wcr_xbar_crd:	 3,	/* LLP crossbar credit */
-			wcr_f_bad_pkt:	 1,	/* Force bad llp pkt enable */
-			wcr_dir_con:	 1,	/* widget direct connect */
-			wcr_e_thresh:	 5,	/* elasticity threshold */
-			wcr_rsvd:	41;	/* unused */
-        } wcr_fields_s;
+	uint64_t wcr_reg_value;
+	struct {
+		uint64_t wcr_widget_id:4,	/* LLP crossbar credit */
+		 wcr_tag_mode:1,	/* Tag mode */
+		 wcr_rsvd1:8,	/* Reserved */
+		 wcr_xbar_crd:3,	/* LLP crossbar credit */
+		 wcr_f_bad_pkt:1,	/* Force bad llp pkt enable */
+		 wcr_dir_con:1,	/* widget direct connect */
+		 wcr_e_thresh:5,	/* elasticity threshold */
+		 wcr_rsvd:41;	/* unused */
+	} wcr_fields_s;
 } hubii_wcr_t;
 
 #define iwcr_dir_con    wcr_fields_s.wcr_dir_con
@@ -3436,41 +3324,35 @@
    performed */
 
 typedef union io_perf_sel {
-        uint64_t perf_sel_reg;
-        struct {
-               uint64_t	perf_ippr0 :  4,
-				perf_ippr1 :  4,
-				perf_icct  :  8,
-				perf_rsvd  : 48;
-        } perf_sel_bits;
+	uint64_t perf_sel_reg;
+	struct {
+		uint64_t perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48;
+	} perf_sel_bits;
 } io_perf_sel_t;
 
 /* io_perf_cnt is to extract the count from the shub registers. Due to
    hardware problems there is only one counter, not two. */
 
 typedef union io_perf_cnt {
-        uint64_t      perf_cnt;
-        struct {
-               uint64_t	perf_cnt   : 20,
-				perf_rsvd2 : 12,
-				perf_rsvd1 : 32;
-        } perf_cnt_bits;
+	uint64_t perf_cnt;
+	struct {
+		uint64_t perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32;
+	} perf_cnt_bits;
 
 } io_perf_cnt_t;
 
 typedef union iprte_a {
-	uint64_t	entry;
+	uint64_t entry;
 	struct {
-		uint64_t	i_rsvd_1                  :	 3;
-		uint64_t	i_addr			  :	38;
-		uint64_t	i_init			  :	 3;
-		uint64_t	i_source		  :	 8;
-		uint64_t	i_rsvd			  :	 2;
-		uint64_t	i_widget		  :	 4;
-		uint64_t	i_to_cnt		  :	 5;
-		uint64_t       i_vld                     :      1;
+		uint64_t i_rsvd_1:3;
+		uint64_t i_addr:38;
+		uint64_t i_init:3;
+		uint64_t i_source:8;
+		uint64_t i_rsvd:2;
+		uint64_t i_widget:4;
+		uint64_t i_to_cnt:5;
+		uint64_t i_vld:1;
 	} iprte_fields;
 } iprte_a_t;
 
-#endif /* _ASM_IA64_SN_SHUBIO_H */
-
+#endif				/* _ASM_IA64_SN_SHUBIO_H */
diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
index 685435a..20b3001 100644
--- a/include/asm-ia64/sn/sn_cpuid.h
+++ b/include/asm-ia64/sn/sn_cpuid.h
@@ -4,7 +4,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
  */
 
 
@@ -92,24 +92,24 @@
  * NOTE: on non-MP systems, only cpuid 0 exists
  */
 
-extern short physical_node_map[];			/* indexed by nasid to get cnode */
+extern short physical_node_map[];	/* indexed by nasid to get cnode */
 
 /*
  * Macros for retrieving info about current cpu
  */
-#define get_nasid()			(nodepda->phys_cpuid[smp_processor_id()].nasid)
-#define get_subnode()			(nodepda->phys_cpuid[smp_processor_id()].subnode)
-#define get_slice()			(nodepda->phys_cpuid[smp_processor_id()].slice)
-#define get_cnode()			(nodepda->phys_cpuid[smp_processor_id()].cnode)
-#define get_sapicid()			((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
+#define get_nasid()	(sn_nodepda->phys_cpuid[smp_processor_id()].nasid)
+#define get_subnode()	(sn_nodepda->phys_cpuid[smp_processor_id()].subnode)
+#define get_slice()	(sn_nodepda->phys_cpuid[smp_processor_id()].slice)
+#define get_cnode()	(sn_nodepda->phys_cpuid[smp_processor_id()].cnode)
+#define get_sapicid()	((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
 
 /*
  * Macros for retrieving info about an arbitrary cpu
  *	cpuid - logical cpu id
  */
-#define cpuid_to_nasid(cpuid)		(nodepda->phys_cpuid[cpuid].nasid)
-#define cpuid_to_subnode(cpuid)		(nodepda->phys_cpuid[cpuid].subnode)
-#define cpuid_to_slice(cpuid)		(nodepda->phys_cpuid[cpuid].slice)
+#define cpuid_to_nasid(cpuid)		(sn_nodepda->phys_cpuid[cpuid].nasid)
+#define cpuid_to_subnode(cpuid)		(sn_nodepda->phys_cpuid[cpuid].subnode)
+#define cpuid_to_slice(cpuid)		(sn_nodepda->phys_cpuid[cpuid].slice)
 #define cpuid_to_cnodeid(cpuid)		(physical_node_map[cpuid_to_nasid(cpuid)])
 
 
@@ -123,11 +123,8 @@
 
 /*
  * cnodeid_to_nasid - convert a cnodeid to a NASID
- *	Macro relies on pg_data for a node being on the node itself.
- *	Just extract the NASID from the pointer.
- *
  */
-#define cnodeid_to_nasid(cnodeid)	pda->cnodeid_to_nasid_table[cnodeid]
+#define cnodeid_to_nasid(cnodeid)	(sn_cnodeid_to_nasid[cnodeid])
  
 /*
  * nasid_to_cnodeid - convert a NASID to a cnodeid
diff --git a/include/asm-ia64/sn/sn_fru.h b/include/asm-ia64/sn/sn_fru.h
deleted file mode 100644
index 8c21ac3..0000000
--- a/include/asm-ia64/sn/sn_fru.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992-1997,1999-2004 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_SN_FRU_H
-#define _ASM_IA64_SN_SN_FRU_H
-
-#define MAX_DIMMS			8	 /* max # of dimm banks */
-#define MAX_PCIDEV			8	 /* max # of pci devices on a pci bus */
-
-typedef unsigned char confidence_t;
-
-typedef struct kf_mem_s {
-	confidence_t km_confidence; /* confidence level that the memory is bad
-				     * is this necessary ?
-				     */
-	confidence_t km_dimm[MAX_DIMMS];
-				    /* confidence level that dimm[i] is bad
-				     *I think this is the right number
-				     */
-
-} kf_mem_t;
-
-typedef struct kf_cpu_s {
-	confidence_t	kc_confidence; /* confidence level that cpu is bad */
-	confidence_t	kc_icache; /* confidence level that instr. cache is bad */
-	confidence_t	kc_dcache; /* confidence level that data   cache is bad */
-	confidence_t	kc_scache; /* confidence level that sec.   cache is bad */
-	confidence_t	kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */
-} kf_cpu_t;
-
-
-typedef struct kf_pci_bus_s {
-	confidence_t	kpb_belief;	/* confidence level  that the  pci bus is bad */
-	confidence_t	kpb_pcidev_belief[MAX_PCIDEV];
-					/* confidence level that the pci dev is bad */
-} kf_pci_bus_t;
-
-
-#endif /* _ASM_IA64_SN_SN_FRU_H */
-
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 88c31b5..56d74ca 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -8,7 +8,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All rights reserved.
  */
 
 
@@ -35,8 +35,8 @@
 #define  SN_SAL_PRINT_ERROR			   0x02000012
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
 #define  SN_SAL_GET_FIT_COMPT			   0x0200001b	// reentrant
-#define  SN_SAL_GET_SN_INFO                        0x0200001c
 #define  SN_SAL_GET_SAPIC_INFO                     0x0200001d
+#define  SN_SAL_GET_SN_INFO                        0x0200001e
 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
 #define  SN_SAL_CONSOLE_GETC                       0x02000022
 #define  SN_SAL_CONSOLE_PUTS                       0x02000023
@@ -64,6 +64,7 @@
 
 #define  SN_SAL_SYSCTL_IOBRICK_PCI_OP		   0x02000042	// reentrant
 #define	 SN_SAL_IROUTER_OP			   0x02000043
+#define  SN_SAL_SYSCTL_EVENT                       0x02000044
 #define  SN_SAL_IOIF_INTERRUPT			   0x0200004a
 #define  SN_SAL_HWPERF_OP			   0x02000050   // lock
 #define  SN_SAL_IOIF_ERROR_INTERRUPT		   0x02000051
@@ -76,7 +77,8 @@
 #define  SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST	   0x02000058
 
 #define SN_SAL_HUB_ERROR_INTERRUPT		   0x02000060
-
+#define SN_SAL_BTE_RECOVER			   0x02000061
+#define SN_SAL_IOIF_GET_PCI_TOPOLOGY	           0x02000062
 
 /*
  * Service-specific constants
@@ -555,7 +557,8 @@
 ia64_sn_partition_serial_get(void)
 {
 	struct ia64_sal_retval ret_stuff;
-	SAL_CALL(ret_stuff, SN_SAL_PARTITION_SERIAL_GET, 0, 0, 0, 0, 0, 0, 0);
+	ia64_sal_oemcall_reentrant(&ret_stuff, SN_SAL_PARTITION_SERIAL_GET, 0,
+				   0, 0, 0, 0, 0, 0);
 	if (ret_stuff.status != 0)
 	    return 0;
 	return ret_stuff.v0;
@@ -563,11 +566,10 @@
 
 static inline u64
 sn_partition_serial_number_val(void) {
-	if (sn_partition_serial_number) {
-		return(sn_partition_serial_number);
-	} else {
-		return(sn_partition_serial_number = ia64_sn_partition_serial_get());
+	if (unlikely(sn_partition_serial_number == 0)) {
+		sn_partition_serial_number = ia64_sn_partition_serial_get();
 	}
+	return sn_partition_serial_number;
 }
 
 /*
@@ -578,8 +580,8 @@
 ia64_sn_sysctl_partition_get(nasid_t nasid)
 {
 	struct ia64_sal_retval ret_stuff;
-	SAL_CALL(ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,
-		 0, 0, 0, 0, 0, 0);
+	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,
+				0, 0, 0, 0, 0, 0);
 	if (ret_stuff.status != 0)
 	    return INVALID_PARTID;
 	return ((partid_t)ret_stuff.v0);
@@ -593,11 +595,38 @@
 
 static inline partid_t
 sn_local_partid(void) {
-	if (sn_partid < 0) {
-		return (sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id())));
-	} else {
-		return sn_partid;
+	if (unlikely(sn_partid < 0)) {
+		sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id()));
 	}
+	return sn_partid;
+}
+
+/*
+ * Returns the physical address of the partition's reserved page through
+ * an iterative number of calls.
+ *
+ * On first call, 'cookie' and 'len' should be set to 0, and 'addr'
+ * set to the nasid of the partition whose reserved page's address is
+ * being sought.
+ * On subsequent calls, pass the values, that were passed back on the
+ * previous call.
+ *
+ * While the return status equals SALRET_MORE_PASSES, keep calling
+ * this function after first copying 'len' bytes starting at 'addr'
+ * into 'buf'. Once the return status equals SALRET_OK, 'addr' will
+ * be the physical address of the partition's reserved page. If the
+ * return status equals neither of these, an error as occurred.
+ */
+static inline s64
+sn_partition_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)
+{
+	struct ia64_sal_retval rv;
+	ia64_sal_oemcall_reentrant(&rv, SN_SAL_GET_PARTITION_ADDR, *cookie,
+				   *addr, buf, *len, 0, 0, 0);
+	*cookie = rv.v0;
+	*addr = rv.v1;
+	*len = rv.v2;
+	return rv.status;
 }
 
 /*
@@ -619,8 +648,8 @@
 sn_register_xp_addr_region(u64 paddr, u64 len, int operation)
 {
 	struct ia64_sal_retval ret_stuff;
-	SAL_CALL(ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len, (u64)operation,
-		 0, 0, 0, 0);
+	ia64_sal_oemcall(&ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len,
+			 (u64)operation, 0, 0, 0, 0);
 	return ret_stuff.status;
 }
 
@@ -644,8 +673,8 @@
 	} else {
 		call = SN_SAL_NO_FAULT_ZONE_PHYSICAL;
 	}
-	SAL_CALL(ret_stuff, call, start_addr, end_addr, return_addr, (u64)1,
-		 0, 0, 0);
+	ia64_sal_oemcall(&ret_stuff, call, start_addr, end_addr, return_addr,
+			 (u64)1, 0, 0, 0);
 	return ret_stuff.status;
 }
 
@@ -666,8 +695,8 @@
 sn_change_coherence(u64 *new_domain, u64 *old_domain)
 {
 	struct ia64_sal_retval ret_stuff;
-	SAL_CALL(ret_stuff, SN_SAL_COHERENCE, new_domain, old_domain, 0, 0,
-		 0, 0, 0);
+	ia64_sal_oemcall(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,
+			 (u64)old_domain, 0, 0, 0, 0, 0);
 	return ret_stuff.status;
 }
 
@@ -686,8 +715,8 @@
 	cnodeid = nasid_to_cnodeid(get_node_number(paddr));
 	// spin_lock(&NODEPDA(cnodeid)->bist_lock);
 	local_irq_save(irq_flags);
-	SAL_CALL_NOLOCK(ret_stuff, SN_SAL_MEMPROTECT, paddr, len, nasid_array,
-		 perms, 0, 0, 0);
+	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
+				(u64)nasid_array, perms, 0, 0, 0);
 	local_irq_restore(irq_flags);
 	// spin_unlock(&NODEPDA(cnodeid)->bist_lock);
 	return ret_stuff.status;
@@ -849,6 +878,19 @@
 	return (int) rv.v0;
 }
 
+/*
+ * Set up a node as the point of contact for system controller
+ * environmental event delivery.
+ */
+static inline int
+ia64_sn_sysctl_event_init(nasid_t nasid)
+{
+        struct ia64_sal_retval rv;
+        SAL_CALL_REENTRANT(rv, SN_SAL_SYSCTL_EVENT, (u64) nasid,
+			   0, 0, 0, 0, 0, 0);
+        return (int) rv.v0;
+}
+
 /**
  * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
  * @nasid: NASID of node to read
@@ -1012,4 +1054,29 @@
 	return (int) rv.status;
 }
 
+static inline int
+ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab,
+			      u64 buf, u64 len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY,
+		rack, bay, slot, slab, buf, len, 0);
+	return (int) rv.status;
+}
+
+/*
+ * BTE error recovery is implemented in SAL
+ */
+static inline int
+ia64_sn_bte_recovery(nasid_t nasid)
+{
+	struct ia64_sal_retval rv;
+
+	rv.status = 0;
+	SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, 0, 0, 0, 0, 0, 0, 0);
+	if (rv.status == SALRET_NOT_IMPLEMENTED)
+		return 0;
+	return (int) rv.status;
+}
+
 #endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/sn/sndrv.h b/include/asm-ia64/sn/sndrv.h
deleted file mode 100644
index aa00d42..0000000
--- a/include/asm-ia64/sn/sndrv.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2002-2004 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-#ifndef _ASM_IA64_SN_SNDRV_H
-#define _ASM_IA64_SN_SNDRV_H
-
-/* ioctl commands */
-#define SNDRV_GET_ROUTERINFO		1
-#define SNDRV_GET_INFOSIZE		2
-#define SNDRV_GET_HUBINFO		3
-#define SNDRV_GET_FLASHLOGSIZE		4
-#define SNDRV_SET_FLASHSYNC		5
-#define SNDRV_GET_FLASHLOGDATA		6
-#define SNDRV_GET_FLASHLOGALL		7
-
-#define SNDRV_SET_HISTOGRAM_TYPE	14
-
-#define SNDRV_ELSC_COMMAND		19
-#define	SNDRV_CLEAR_LOG			20
-#define	SNDRV_INIT_LOG			21
-#define	SNDRV_GET_PIMM_PSC		22
-#define SNDRV_SET_PARTITION		23
-#define SNDRV_GET_PARTITION		24
-
-/* see synergy_perf_ioctl() */
-#define SNDRV_GET_SYNERGY_VERSION	30
-#define SNDRV_GET_SYNERGY_STATUS	31
-#define SNDRV_GET_SYNERGYINFO		32
-#define SNDRV_SYNERGY_APPEND		33
-#define SNDRV_SYNERGY_ENABLE		34
-#define SNDRV_SYNERGY_FREQ		35
-
-/* Devices */
-#define SNDRV_UKNOWN_DEVICE		-1
-#define SNDRV_ROUTER_DEVICE		1
-#define SNDRV_HUB_DEVICE		2
-#define SNDRV_ELSC_NVRAM_DEVICE		3
-#define SNDRV_ELSC_CONTROLLER_DEVICE	4
-#define SNDRV_SYSCTL_SUBCH		5
-#define SNDRV_SYNERGY_DEVICE		6
-
-#endif /* _ASM_IA64_SN_SNDRV_H */
diff --git a/include/asm-ia64/sn/tioca.h b/include/asm-ia64/sn/tioca.h
new file mode 100644
index 0000000..bc1aacf
--- /dev/null
+++ b/include/asm-ia64/sn/tioca.h
@@ -0,0 +1,596 @@
+#ifndef _ASM_IA64_SN_TIO_TIOCA_H
+#define _ASM_IA64_SN_TIO_TIOCA_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#define TIOCA_PART_NUM	0xE020
+#define TIOCA_MFGR_NUM	0x24
+#define TIOCA_REV_A	0x1
+
+/*
+ * Register layout for TIO:CA.  See below for bitmasks for each register.
+ */
+
+struct tioca {
+	uint64_t	ca_id;				/* 0x000000 */
+	uint64_t	ca_control1;			/* 0x000008 */
+	uint64_t	ca_control2;			/* 0x000010 */
+	uint64_t	ca_status1;			/* 0x000018 */
+	uint64_t	ca_status2;			/* 0x000020 */
+	uint64_t	ca_gart_aperature;		/* 0x000028 */
+	uint64_t	ca_gfx_detach;			/* 0x000030 */
+	uint64_t	ca_inta_dest_addr;		/* 0x000038 */
+	uint64_t	ca_intb_dest_addr;		/* 0x000040 */
+	uint64_t	ca_err_int_dest_addr;		/* 0x000048 */
+	uint64_t	ca_int_status;			/* 0x000050 */
+	uint64_t	ca_int_status_alias;		/* 0x000058 */
+	uint64_t	ca_mult_error;			/* 0x000060 */
+	uint64_t	ca_mult_error_alias;		/* 0x000068 */
+	uint64_t	ca_first_error;			/* 0x000070 */
+	uint64_t	ca_int_mask;			/* 0x000078 */
+	uint64_t	ca_crm_pkterr_type;		/* 0x000080 */
+	uint64_t	ca_crm_pkterr_type_alias;	/* 0x000088 */
+	uint64_t	ca_crm_ct_error_detail_1;	/* 0x000090 */
+	uint64_t	ca_crm_ct_error_detail_2;	/* 0x000098 */
+	uint64_t	ca_crm_tnumto;			/* 0x0000A0 */
+	uint64_t	ca_gart_err;			/* 0x0000A8 */
+	uint64_t	ca_pcierr_type;			/* 0x0000B0 */
+	uint64_t	ca_pcierr_addr;			/* 0x0000B8 */
+
+	uint64_t	ca_pad_0000C0[3];		/* 0x0000{C0..D0} */
+
+	uint64_t	ca_pci_rd_buf_flush;		/* 0x0000D8 */
+	uint64_t	ca_pci_dma_addr_extn;		/* 0x0000E0 */
+	uint64_t	ca_agp_dma_addr_extn;		/* 0x0000E8 */
+	uint64_t	ca_force_inta;			/* 0x0000F0 */
+	uint64_t	ca_force_intb;			/* 0x0000F8 */
+	uint64_t	ca_debug_vector_sel;		/* 0x000100 */
+	uint64_t	ca_debug_mux_core_sel;		/* 0x000108 */
+	uint64_t	ca_debug_mux_pci_sel;		/* 0x000110 */
+	uint64_t	ca_debug_domain_sel;		/* 0x000118 */
+
+	uint64_t	ca_pad_000120[28];		/* 0x0001{20..F8} */
+
+	uint64_t	ca_gart_ptr_table;		/* 0x200 */
+	uint64_t	ca_gart_tlb_addr[8];		/* 0x2{08..40} */
+};
+
+/*
+ * Mask/shift definitions for TIO:CA registers.  The convention here is
+ * to mainly use the names as they appear in the "TIO AEGIS Programmers'
+ * Reference" with a CA_ prefix added.  Some exceptions were made to fix
+ * duplicate field names or to generalize fields that are common to
+ * different registers (ca_debug_mux_core_sel and ca_debug_mux_pci_sel for
+ * example).
+ *
+ * Fields consisting of a single bit have a single #define have a single
+ * macro declaration to mask the bit.  Fields consisting of multiple bits
+ * have two declarations: one to mask the proper bits in a register, and 
+ * a second with the suffix "_SHFT" to identify how far the mask needs to
+ * be shifted right to get its base value.
+ */
+
+/* ==== ca_control1 */
+#define CA_SYS_BIG_END			(1ull << 0)
+#define CA_DMA_AGP_SWAP			(1ull << 1)
+#define CA_DMA_PCI_SWAP			(1ull << 2)
+#define CA_PIO_IO_SWAP			(1ull << 3)
+#define CA_PIO_MEM_SWAP			(1ull << 4)
+#define CA_GFX_WR_SWAP			(1ull << 5)
+#define CA_AGP_FW_ENABLE		(1ull << 6)
+#define CA_AGP_CAL_CYCLE		(0x7ull << 7)
+#define CA_AGP_CAL_CYCLE_SHFT		7
+#define CA_AGP_CAL_PRSCL_BYP		(1ull << 10)
+#define CA_AGP_INIT_CAL_ENB		(1ull << 11)
+#define CA_INJ_ADDR_PERR		(1ull << 12)
+#define CA_INJ_DATA_PERR		(1ull << 13)
+	/* bits 15:14 unused */
+#define CA_PCIM_IO_NBE_AD		(0x7ull << 16)
+#define CA_PCIM_IO_NBE_AD_SHFT		16
+#define CA_PCIM_FAST_BTB_ENB		(1ull << 19)
+	/* bits 23:20 unused */
+#define CA_PIO_ADDR_OFFSET		(0xffull << 24)
+#define CA_PIO_ADDR_OFFSET_SHFT		24
+	/* bits 35:32 unused */
+#define CA_AGPDMA_OP_COMBDELAY		(0x1full << 36)
+#define CA_AGPDMA_OP_COMBDELAY_SHFT	36
+	/* bit 41 unused */
+#define CA_AGPDMA_OP_ENB_COMBDELAY	(1ull << 42)
+#define	CA_PCI_INT_LPCNT		(0xffull << 44)
+#define CA_PCI_INT_LPCNT_SHFT		44
+	/* bits 63:52 unused */
+
+/* ==== ca_control2 */
+#define CA_AGP_LATENCY_TO		(0xffull << 0)
+#define CA_AGP_LATENCY_TO_SHFT		0
+#define CA_PCI_LATENCY_TO		(0xffull << 8)
+#define CA_PCI_LATENCY_TO_SHFT		8
+#define CA_PCI_MAX_RETRY		(0x3ffull << 16)
+#define CA_PCI_MAX_RETRY_SHFT		16
+	/* bits 27:26 unused */
+#define CA_RT_INT_EN			(0x3ull << 28)
+#define CA_RT_INT_EN_SHFT			28
+#define CA_MSI_INT_ENB			(1ull << 30)
+#define CA_PCI_ARB_ERR_ENB		(1ull << 31)
+#define CA_GART_MEM_PARAM		(0x3ull << 32)
+#define CA_GART_MEM_PARAM_SHFT		32
+#define CA_GART_RD_PREFETCH_ENB		(1ull << 34)
+#define CA_GART_WR_PREFETCH_ENB		(1ull << 35)
+#define CA_GART_FLUSH_TLB		(1ull << 36)
+	/* bits 39:37 unused */
+#define CA_CRM_TNUMTO_PERIOD		(0x1fffull << 40)
+#define CA_CRM_TNUMTO_PERIOD_SHFT	40
+	/* bits 55:53 unused */
+#define CA_CRM_TNUMTO_ENB		(1ull << 56)
+#define CA_CRM_PRESCALER_BYP		(1ull << 57)
+	/* bits 59:58 unused */
+#define CA_CRM_MAX_CREDIT		(0x7ull << 60)
+#define CA_CRM_MAX_CREDIT_SHFT		60
+	/* bit 63 unused */
+
+/* ==== ca_status1 */
+#define CA_CORELET_ID			(0x3ull << 0)
+#define CA_CORELET_ID_SHFT		0
+#define CA_INTA_N			(1ull << 2)
+#define CA_INTB_N			(1ull << 3)
+#define CA_CRM_CREDIT_AVAIL		(0x7ull << 4)
+#define CA_CRM_CREDIT_AVAIL_SHFT	4
+	/* bit 7 unused */
+#define CA_CRM_SPACE_AVAIL		(0x7full << 8)
+#define CA_CRM_SPACE_AVAIL_SHFT		8
+	/* bit 15 unused */
+#define CA_GART_TLB_VAL			(0xffull << 16)
+#define CA_GART_TLB_VAL_SHFT		16
+	/* bits 63:24 unused */
+
+/* ==== ca_status2 */
+#define CA_GFX_CREDIT_AVAIL		(0xffull << 0)
+#define CA_GFX_CREDIT_AVAIL_SHFT	0
+#define CA_GFX_OPQ_AVAIL		(0xffull << 8)
+#define CA_GFX_OPQ_AVAIL_SHFT		8
+#define CA_GFX_WRBUFF_AVAIL		(0xffull << 16)
+#define CA_GFX_WRBUFF_AVAIL_SHFT	16
+#define CA_ADMA_OPQ_AVAIL		(0xffull << 24)
+#define CA_ADMA_OPQ_AVAIL_SHFT		24
+#define CA_ADMA_WRBUFF_AVAIL		(0xffull << 32)
+#define CA_ADMA_WRBUFF_AVAIL_SHFT	32
+#define CA_ADMA_RDBUFF_AVAIL		(0x7full << 40)
+#define CA_ADMA_RDBUFF_AVAIL_SHFT	40
+#define CA_PCI_PIO_OP_STAT		(1ull << 47)
+#define CA_PDMA_OPQ_AVAIL		(0xfull << 48)
+#define CA_PDMA_OPQ_AVAIL_SHFT		48
+#define CA_PDMA_WRBUFF_AVAIL		(0xfull << 52)
+#define CA_PDMA_WRBUFF_AVAIL_SHFT	52
+#define CA_PDMA_RDBUFF_AVAIL		(0x3ull << 56)
+#define CA_PDMA_RDBUFF_AVAIL_SHFT	56
+	/* bits 63:58 unused */
+
+/* ==== ca_gart_aperature */
+#define CA_GART_AP_ENB_AGP		(1ull << 0)
+#define CA_GART_PAGE_SIZE		(1ull << 1)
+#define CA_GART_AP_ENB_PCI		(1ull << 2)
+	/* bits 11:3 unused */
+#define CA_GART_AP_SIZE			(0x3ffull << 12)
+#define CA_GART_AP_SIZE_SHFT		12
+#define CA_GART_AP_BASE			(0x3ffffffffffull << 22)
+#define CA_GART_AP_BASE_SHFT		22
+
+/* ==== ca_inta_dest_addr
+   ==== ca_intb_dest_addr 
+   ==== ca_err_int_dest_addr */
+	/* bits 2:0 unused */
+#define CA_INT_DEST_ADDR		(0x7ffffffffffffull << 3)
+#define CA_INT_DEST_ADDR_SHFT		3
+	/* bits 55:54 unused */
+#define CA_INT_DEST_VECT		(0xffull << 56)
+#define CA_INT_DEST_VECT_SHFT		56
+
+/* ==== ca_int_status */
+/* ==== ca_int_status_alias */
+/* ==== ca_mult_error */
+/* ==== ca_mult_error_alias */
+/* ==== ca_first_error */
+/* ==== ca_int_mask */
+#define CA_PCI_ERR			(1ull << 0)
+	/* bits 3:1 unused */
+#define CA_GART_FETCH_ERR		(1ull << 4)
+#define CA_GFX_WR_OVFLW			(1ull << 5)
+#define CA_PIO_REQ_OVFLW		(1ull << 6)
+#define CA_CRM_PKTERR			(1ull << 7)
+#define CA_CRM_DVERR			(1ull << 8)
+#define CA_TNUMTO			(1ull << 9)
+#define CA_CXM_RSP_CRED_OVFLW		(1ull << 10)
+#define CA_CXM_REQ_CRED_OVFLW		(1ull << 11)
+#define CA_PIO_INVALID_ADDR		(1ull << 12)
+#define CA_PCI_ARB_TO			(1ull << 13)
+#define CA_AGP_REQ_OFLOW		(1ull << 14)
+#define CA_SBA_TYPE1_ERR		(1ull << 15)
+	/* bit 16 unused */
+#define CA_INTA				(1ull << 17)
+#define CA_INTB				(1ull << 18)
+#define CA_MULT_INTA			(1ull << 19)
+#define CA_MULT_INTB			(1ull << 20)
+#define CA_GFX_CREDIT_OVFLW		(1ull << 21)
+	/* bits 63:22 unused */
+
+/* ==== ca_crm_pkterr_type */
+/* ==== ca_crm_pkterr_type_alias */
+#define CA_CRM_PKTERR_SBERR_HDR		(1ull << 0)
+#define CA_CRM_PKTERR_DIDN		(1ull << 1)
+#define CA_CRM_PKTERR_PACTYPE		(1ull << 2)
+#define CA_CRM_PKTERR_INV_TNUM		(1ull << 3)
+#define CA_CRM_PKTERR_ADDR_RNG		(1ull << 4)
+#define CA_CRM_PKTERR_ADDR_ALGN		(1ull << 5)
+#define CA_CRM_PKTERR_HDR_PARAM		(1ull << 6)
+#define CA_CRM_PKTERR_CW_ERR		(1ull << 7)
+#define CA_CRM_PKTERR_SBERR_NH		(1ull << 8)
+#define CA_CRM_PKTERR_EARLY_TERM	(1ull << 9)
+#define CA_CRM_PKTERR_EARLY_TAIL	(1ull << 10)
+#define CA_CRM_PKTERR_MSSNG_TAIL	(1ull << 11)
+#define CA_CRM_PKTERR_MSSNG_HDR		(1ull << 12)
+	/* bits 15:13 unused */
+#define CA_FIRST_CRM_PKTERR_SBERR_HDR	(1ull << 16)
+#define CA_FIRST_CRM_PKTERR_DIDN	(1ull << 17)
+#define CA_FIRST_CRM_PKTERR_PACTYPE	(1ull << 18)
+#define CA_FIRST_CRM_PKTERR_INV_TNUM	(1ull << 19)
+#define CA_FIRST_CRM_PKTERR_ADDR_RNG	(1ull << 20)
+#define CA_FIRST_CRM_PKTERR_ADDR_ALGN	(1ull << 21)
+#define CA_FIRST_CRM_PKTERR_HDR_PARAM	(1ull << 22)
+#define CA_FIRST_CRM_PKTERR_CW_ERR	(1ull << 23)
+#define CA_FIRST_CRM_PKTERR_SBERR_NH	(1ull << 24)
+#define CA_FIRST_CRM_PKTERR_EARLY_TERM	(1ull << 25)
+#define CA_FIRST_CRM_PKTERR_EARLY_TAIL	(1ull << 26)
+#define CA_FIRST_CRM_PKTERR_MSSNG_TAIL	(1ull << 27)
+#define CA_FIRST_CRM_PKTERR_MSSNG_HDR	(1ull << 28)
+	/* bits 63:29 unused */
+
+/* ==== ca_crm_ct_error_detail_1 */
+#define CA_PKT_TYPE			(0xfull << 0)
+#define CA_PKT_TYPE_SHFT		0
+#define CA_SRC_ID			(0x3ull << 4)
+#define CA_SRC_ID_SHFT			4
+#define CA_DATA_SZ			(0x3ull << 6)
+#define CA_DATA_SZ_SHFT			6
+#define CA_TNUM				(0xffull << 8)
+#define CA_TNUM_SHFT			8
+#define CA_DW_DATA_EN			(0xffull << 16)
+#define CA_DW_DATA_EN_SHFT		16
+#define CA_GFX_CRED			(0xffull << 24)
+#define CA_GFX_CRED_SHFT		24
+#define CA_MEM_RD_PARAM			(0x3ull << 32)
+#define CA_MEM_RD_PARAM_SHFT		32
+#define CA_PIO_OP			(1ull << 34)
+#define CA_CW_ERR			(1ull << 35)
+	/* bits 62:36 unused */
+#define CA_VALID			(1ull << 63)
+
+/* ==== ca_crm_ct_error_detail_2 */
+	/* bits 2:0 unused */
+#define CA_PKT_ADDR			(0x1fffffffffffffull << 3)
+#define CA_PKT_ADDR_SHFT		3
+	/* bits 63:56 unused */
+
+/* ==== ca_crm_tnumto */
+#define CA_CRM_TNUMTO_VAL		(0xffull << 0)
+#define CA_CRM_TNUMTO_VAL_SHFT		0
+#define CA_CRM_TNUMTO_WR		(1ull << 8)
+	/* bits 63:9 unused */
+
+/* ==== ca_gart_err */
+#define CA_GART_ERR_SOURCE		(0x3ull << 0)
+#define CA_GART_ERR_SOURCE_SHFT		0
+	/* bits 3:2 unused */
+#define CA_GART_ERR_ADDR		(0xfffffffffull << 4)
+#define CA_GART_ERR_ADDR_SHFT		4
+	/* bits 63:40 unused */
+
+/* ==== ca_pcierr_type */
+#define CA_PCIERR_DATA			(0xffffffffull << 0)
+#define CA_PCIERR_DATA_SHFT		0
+#define CA_PCIERR_ENB			(0xfull << 32)
+#define CA_PCIERR_ENB_SHFT		32
+#define CA_PCIERR_CMD			(0xfull << 36)
+#define CA_PCIERR_CMD_SHFT		36
+#define CA_PCIERR_A64			(1ull << 40)
+#define CA_PCIERR_SLV_SERR		(1ull << 41)
+#define CA_PCIERR_SLV_WR_PERR		(1ull << 42)
+#define CA_PCIERR_SLV_RD_PERR		(1ull << 43)
+#define CA_PCIERR_MST_SERR		(1ull << 44)
+#define CA_PCIERR_MST_WR_PERR		(1ull << 45)
+#define CA_PCIERR_MST_RD_PERR		(1ull << 46)
+#define CA_PCIERR_MST_MABT		(1ull << 47)
+#define CA_PCIERR_MST_TABT		(1ull << 48)
+#define CA_PCIERR_MST_RETRY_TOUT	(1ull << 49)
+
+#define CA_PCIERR_TYPES \
+	(CA_PCIERR_A64|CA_PCIERR_SLV_SERR| \
+	 CA_PCIERR_SLV_WR_PERR|CA_PCIERR_SLV_RD_PERR| \
+	 CA_PCIERR_MST_SERR|CA_PCIERR_MST_WR_PERR|CA_PCIERR_MST_RD_PERR| \
+	 CA_PCIERR_MST_MABT|CA_PCIERR_MST_TABT|CA_PCIERR_MST_RETRY_TOUT)
+
+	/* bits 63:50 unused */
+
+/* ==== ca_pci_dma_addr_extn */
+#define CA_UPPER_NODE_OFFSET		(0x3full << 0)
+#define CA_UPPER_NODE_OFFSET_SHFT	0
+	/* bits 7:6 unused */
+#define CA_CHIPLET_ID			(0x3ull << 8)
+#define CA_CHIPLET_ID_SHFT		8
+	/* bits 11:10 unused */
+#define CA_PCI_DMA_NODE_ID		(0xffffull << 12)
+#define CA_PCI_DMA_NODE_ID_SHFT		12
+	/* bits 27:26 unused */
+#define CA_PCI_DMA_PIO_MEM_TYPE		(1ull << 28)
+	/* bits 63:29 unused */
+
+
+/* ==== ca_agp_dma_addr_extn */
+	/* bits 19:0 unused */
+#define CA_AGP_DMA_NODE_ID		(0xffffull << 20)
+#define CA_AGP_DMA_NODE_ID_SHFT		20
+	/* bits 27:26 unused */
+#define CA_AGP_DMA_PIO_MEM_TYPE		(1ull << 28)
+	/* bits 63:29 unused */
+
+/* ==== ca_debug_vector_sel */
+#define CA_DEBUG_MN_VSEL		(0xfull << 0)
+#define CA_DEBUG_MN_VSEL_SHFT		0
+#define CA_DEBUG_PP_VSEL		(0xfull << 4)
+#define CA_DEBUG_PP_VSEL_SHFT		4
+#define CA_DEBUG_GW_VSEL		(0xfull << 8)
+#define CA_DEBUG_GW_VSEL_SHFT		8
+#define CA_DEBUG_GT_VSEL		(0xfull << 12)
+#define CA_DEBUG_GT_VSEL_SHFT		12
+#define CA_DEBUG_PD_VSEL		(0xfull << 16)
+#define CA_DEBUG_PD_VSEL_SHFT		16
+#define CA_DEBUG_AD_VSEL		(0xfull << 20)
+#define CA_DEBUG_AD_VSEL_SHFT		20
+#define CA_DEBUG_CX_VSEL		(0xfull << 24)
+#define CA_DEBUG_CX_VSEL_SHFT		24
+#define CA_DEBUG_CR_VSEL		(0xfull << 28)
+#define CA_DEBUG_CR_VSEL_SHFT		28
+#define CA_DEBUG_BA_VSEL		(0xfull << 32)
+#define CA_DEBUG_BA_VSEL_SHFT		32
+#define CA_DEBUG_PE_VSEL		(0xfull << 36)
+#define CA_DEBUG_PE_VSEL_SHFT		36
+#define CA_DEBUG_BO_VSEL		(0xfull << 40)
+#define CA_DEBUG_BO_VSEL_SHFT		40
+#define CA_DEBUG_BI_VSEL		(0xfull << 44)
+#define CA_DEBUG_BI_VSEL_SHFT		44
+#define CA_DEBUG_AS_VSEL		(0xfull << 48)
+#define CA_DEBUG_AS_VSEL_SHFT		48
+#define CA_DEBUG_PS_VSEL		(0xfull << 52)
+#define CA_DEBUG_PS_VSEL_SHFT		52
+#define CA_DEBUG_PM_VSEL		(0xfull << 56)
+#define CA_DEBUG_PM_VSEL_SHFT		56
+	/* bits 63:60 unused */
+
+/* ==== ca_debug_mux_core_sel */
+/* ==== ca_debug_mux_pci_sel */
+#define CA_DEBUG_MSEL0			(0x7ull << 0)
+#define CA_DEBUG_MSEL0_SHFT		0
+	/* bit 3 unused */
+#define CA_DEBUG_NSEL0			(0x7ull << 4)
+#define CA_DEBUG_NSEL0_SHFT		4
+	/* bit 7 unused */
+#define CA_DEBUG_MSEL1			(0x7ull << 8)
+#define CA_DEBUG_MSEL1_SHFT		8
+	/* bit 11 unused */
+#define CA_DEBUG_NSEL1			(0x7ull << 12)
+#define CA_DEBUG_NSEL1_SHFT		12
+	/* bit 15 unused */
+#define CA_DEBUG_MSEL2			(0x7ull << 16)
+#define CA_DEBUG_MSEL2_SHFT		16
+	/* bit 19 unused */
+#define CA_DEBUG_NSEL2			(0x7ull << 20)
+#define CA_DEBUG_NSEL2_SHFT		20
+	/* bit 23 unused */
+#define CA_DEBUG_MSEL3			(0x7ull << 24)
+#define CA_DEBUG_MSEL3_SHFT		24
+	/* bit 27 unused */
+#define CA_DEBUG_NSEL3			(0x7ull << 28)
+#define CA_DEBUG_NSEL3_SHFT		28
+	/* bit 31 unused */
+#define CA_DEBUG_MSEL4			(0x7ull << 32)
+#define CA_DEBUG_MSEL4_SHFT		32
+	/* bit 35 unused */
+#define CA_DEBUG_NSEL4			(0x7ull << 36)
+#define CA_DEBUG_NSEL4_SHFT		36
+	/* bit 39 unused */
+#define CA_DEBUG_MSEL5			(0x7ull << 40)
+#define CA_DEBUG_MSEL5_SHFT		40
+	/* bit 43 unused */
+#define CA_DEBUG_NSEL5			(0x7ull << 44)
+#define CA_DEBUG_NSEL5_SHFT		44
+	/* bit 47 unused */
+#define CA_DEBUG_MSEL6			(0x7ull << 48)
+#define CA_DEBUG_MSEL6_SHFT		48
+	/* bit 51 unused */
+#define CA_DEBUG_NSEL6			(0x7ull << 52)
+#define CA_DEBUG_NSEL6_SHFT		52
+	/* bit 55 unused */
+#define CA_DEBUG_MSEL7			(0x7ull << 56)
+#define CA_DEBUG_MSEL7_SHFT		56
+	/* bit 59 unused */
+#define CA_DEBUG_NSEL7			(0x7ull << 60)
+#define CA_DEBUG_NSEL7_SHFT		60
+	/* bit 63 unused */
+
+
+/* ==== ca_debug_domain_sel */
+#define CA_DEBUG_DOMAIN_L		(1ull << 0)
+#define CA_DEBUG_DOMAIN_H		(1ull << 1)
+	/* bits 63:2 unused */
+
+/* ==== ca_gart_ptr_table */
+#define CA_GART_PTR_VAL			(1ull << 0)
+	/* bits 11:1 unused */
+#define CA_GART_PTR_ADDR		(0xfffffffffffull << 12)
+#define CA_GART_PTR_ADDR_SHFT		12
+	/* bits 63:56 unused */
+
+/* ==== ca_gart_tlb_addr[0-7] */
+#define CA_GART_TLB_ADDR		(0xffffffffffffffull << 0)
+#define CA_GART_TLB_ADDR_SHFT		0
+	/* bits 62:56 unused */
+#define CA_GART_TLB_ENTRY_VAL		(1ull << 63)
+
+/*
+ * PIO address space ranges for TIO:CA
+ */
+
+/* CA internal registers */
+#define CA_PIO_ADMIN			0x00000000
+#define CA_PIO_ADMIN_LEN		0x00010000
+
+/* GFX Write Buffer - Diagnostics */
+#define CA_PIO_GFX			0x00010000
+#define CA_PIO_GFX_LEN			0x00010000
+
+/* AGP DMA Write Buffer - Diagnostics */
+#define CA_PIO_AGP_DMAWRITE		0x00020000
+#define CA_PIO_AGP_DMAWRITE_LEN		0x00010000
+
+/* AGP DMA READ Buffer - Diagnostics */
+#define CA_PIO_AGP_DMAREAD		0x00030000
+#define CA_PIO_AGP_DMAREAD_LEN		0x00010000
+
+/* PCI Config Type 0 */
+#define CA_PIO_PCI_TYPE0_CONFIG		0x01000000
+#define CA_PIO_PCI_TYPE0_CONFIG_LEN	0x01000000
+
+/* PCI Config Type 1 */
+#define CA_PIO_PCI_TYPE1_CONFIG		0x02000000
+#define CA_PIO_PCI_TYPE1_CONFIG_LEN	0x01000000
+
+/* PCI I/O Cycles - mapped to PCI Address 0x00000000-0x04ffffff */
+#define CA_PIO_PCI_IO			0x03000000
+#define CA_PIO_PCI_IO_LEN		0x05000000
+
+/* PCI MEM Cycles - mapped to PCI with CA_PIO_ADDR_OFFSET of ca_control1 */
+/*	use Fast Write if enabled and coretalk packet type is a GFX request */
+#define CA_PIO_PCI_MEM_OFFSET		0x08000000
+#define CA_PIO_PCI_MEM_OFFSET_LEN	0x08000000
+
+/* PCI MEM Cycles - mapped to PCI Address 0x00000000-0xbfffffff */
+/*	use Fast Write if enabled and coretalk packet type is a GFX request */
+#define CA_PIO_PCI_MEM			0x40000000
+#define CA_PIO_PCI_MEM_LEN		0xc0000000
+
+/*
+ * DMA space
+ *
+ * The CA aperature (ie. bus address range) mapped by the GART is segmented into
+ * two parts.  The lower portion of the aperature is used for mapping 32 bit
+ * PCI addresses which are managed by the dma interfaces in this file.  The
+ * upper poprtion of the aperature is used for mapping 48 bit AGP addresses.
+ * The AGP portion of the aperature is managed by the agpgart_be.c driver
+ * in drivers/linux/agp.  There are ca-specific hooks in that driver to
+ * manipulate the gart, but management of the AGP portion of the aperature
+ * is the responsibility of that driver.
+ *
+ * CA allows three main types of DMA mapping:
+ *
+ * PCI 64-bit	Managed by this driver
+ * PCI 32-bit 	Managed by this driver
+ * AGP 48-bit	Managed by hooks in the /dev/agpgart driver
+ *
+ * All of the above can optionally be remapped through the GART.  The following
+ * table lists the combinations of addressing types and GART remapping that
+ * is currently supported by the driver (h/w supports all, s/w limits this):
+ *
+ *		PCI64		PCI32		AGP48
+ * GART		no		yes		yes
+ * Direct	yes		yes		no
+ *
+ * GART remapping of PCI64 is not done because there is no need to.  The
+ * 64 bit PCI address holds all of the information necessary to target any
+ * memory in the system.
+ *
+ * AGP48 is always mapped through the GART.  Management of the AGP48 portion
+ * of the aperature is the responsibility of code in the agpgart_be driver.
+ *
+ * The non-64 bit bus address space will currently be partitioned like this:
+ *
+ *	0xffff_ffff_ffff	+--------
+ *				| AGP48 direct
+ *				| Space managed by this driver
+ *	CA_AGP_DIRECT_BASE	+--------
+ *				| AGP GART mapped (gfx aperature)
+ *				| Space managed by /dev/agpgart driver
+ *				| This range is exposed to the agpgart
+ * 				| driver as the "graphics aperature"
+ *	CA_AGP_MAPPED_BASE	+-----
+ *				| PCI GART mapped
+ *				| Space managed by this driver		
+ *	CA_PCI32_MAPPED_BASE	+----
+ *				| PCI32 direct
+ *				| Space managed by this driver
+ *	0xC000_0000		+--------
+ *	(CA_PCI32_DIRECT_BASE)
+ *
+ * The bus address range CA_PCI32_MAPPED_BASE through CA_AGP_DIRECT_BASE
+ * is what we call the CA aperature.  Addresses falling in this range will
+ * be remapped using the GART.
+ *
+ * The bus address range CA_AGP_MAPPED_BASE through CA_AGP_DIRECT_BASE
+ * is what we call the graphics aperature.  This is a subset of the CA
+ * aperature and is under the control of the agpgart_be driver.
+ *
+ * CA_PCI32_MAPPED_BASE, CA_AGP_MAPPED_BASE, and CA_AGP_DIRECT_BASE are
+ * somewhat arbitrary values.  The known constraints on choosing these is:
+ *
+ * 1)  CA_AGP_DIRECT_BASE-CA_PCI32_MAPPED_BASE+1 (the CA aperature size)
+ *     must be one of the values supported by the ca_gart_aperature register.
+ *     Currently valid values are: 4MB through 4096MB in powers of 2 increments
+ *
+ * 2)  CA_AGP_DIRECT_BASE-CA_AGP_MAPPED_BASE+1 (the gfx aperature size)
+ *     must be in MB units since that's what the agpgart driver assumes.
+ */
+
+/*
+ * Define Bus DMA ranges.  These are configurable (see constraints above)
+ * and will probably need tuning based on experience.
+ */
+
+
+/*
+ * 11/24/03
+ * CA has an addressing glitch w.r.t. PCI direct 32 bit DMA that makes it
+ * generally unusable.  The problem is that for PCI direct 32 
+ * DMA's, all 32 bits of the bus address are used to form the lower 32 bits
+ * of the coretalk address, and coretalk bits 38:32 come from a register.
+ * Since only PCI bus addresses 0xC0000000-0xFFFFFFFF (1GB) are available
+ * for DMA (the rest is allocated to PIO), host node addresses need to be
+ * such that their lower 32 bits fall in the 0xC0000000-0xffffffff range
+ * as well.  So there can be no PCI32 direct DMA below 3GB!!  For this
+ * reason we set the CA_PCI32_DIRECT_SIZE to 0 which essentially makes
+ * tioca_dma_direct32() a noop but preserves the code flow should this issue
+ * be fixed in a respin.
+ *
+ * For now, all PCI32 DMA's must be mapped through the GART.
+ */
+
+#define CA_PCI32_DIRECT_BASE	0xC0000000UL	/* BASE not configurable */
+#define CA_PCI32_DIRECT_SIZE	0x00000000UL	/* 0 MB */
+
+#define CA_PCI32_MAPPED_BASE	0xC0000000UL
+#define CA_PCI32_MAPPED_SIZE	0x40000000UL	/* 2GB */
+
+#define CA_AGP_MAPPED_BASE	0x80000000UL
+#define CA_AGP_MAPPED_SIZE	0x40000000UL	/* 2GB */
+
+#define CA_AGP_DIRECT_BASE	0x40000000UL	/* 2GB */
+#define CA_AGP_DIRECT_SIZE	0x40000000UL
+
+#define CA_APERATURE_BASE	(CA_AGP_MAPPED_BASE)
+#define CA_APERATURE_SIZE	(CA_AGP_MAPPED_SIZE+CA_PCI32_MAPPED_SIZE)
+
+#endif  /* _ASM_IA64_SN_TIO_TIOCA_H */
diff --git a/include/asm-ia64/sn/tioca_provider.h b/include/asm-ia64/sn/tioca_provider.h
new file mode 100644
index 0000000..b6acc22
--- /dev/null
+++ b/include/asm-ia64/sn/tioca_provider.h
@@ -0,0 +1,206 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H
+#define _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H
+
+#include <asm/sn/tioca.h>
+
+/*
+ * WAR enables
+ * Defines for individual WARs. Each is a bitmask of applicable
+ * part revision numbers. (1 << 1) == rev A, (1 << 2) == rev B,
+ * (3 << 1) == (rev A or rev B), etc
+ */
+
+#define TIOCA_WAR_ENABLED(pv, tioca_common) \
+	((1 << tioca_common->ca_rev) & pv)
+
+  /* TIO:ICE:FRZ:Freezer loses a PIO data ucred on PIO RD RSP with CW error */
+#define PV907908 (1 << 1)
+  /* ATI config space problems after BIOS execution starts */
+#define PV908234 (1 << 1)
+  /* CA:AGPDMA write request data mismatch with ABC1CL merge */
+#define PV895469 (1 << 1)
+  /* TIO:CA TLB invalidate of written GART entries possibly not occuring in CA*/
+#define PV910244 (1 << 1)
+
+struct tioca_dmamap{
+	struct list_head	cad_list;	/* headed by ca_list */
+
+	dma_addr_t		cad_dma_addr;	/* Linux dma handle */
+	uint			cad_gart_entry; /* start entry in ca_gart_pagemap */
+	uint			cad_gart_size;	/* #entries for this map */
+};
+
+/*
+ * Kernel only fields.  Prom may look at this stuff for debugging only.
+ * Access this structure through the ca_kernel_private ptr.
+ */
+
+struct tioca_common ;
+
+struct tioca_kernel {
+	struct tioca_common	*ca_common;	/* tioca this belongs to */
+	struct list_head	ca_list;	/* list of all ca's */
+	struct list_head	ca_dmamaps;
+	spinlock_t		ca_lock;	/* Kernel lock */
+	cnodeid_t		ca_closest_node;
+	struct list_head	*ca_devices;	/* bus->devices */
+
+	/*
+	 * General GART stuff
+	 */
+	uint64_t	ca_ap_size;		/* size of aperature in bytes */
+	uint32_t	ca_gart_entries;	/* # uint64_t entries in gart */
+	uint32_t	ca_ap_pagesize; 	/* aperature page size in bytes */
+	uint64_t	ca_ap_bus_base; 	/* bus address of CA aperature */
+	uint64_t	ca_gart_size;		/* gart size in bytes */
+	uint64_t	*ca_gart;		/* gart table vaddr */
+	uint64_t	ca_gart_coretalk_addr;	/* gart coretalk addr */
+	uint8_t		ca_gart_iscoherent;	/* used in tioca_tlbflush */
+
+	/* PCI GART convenience values */
+	uint64_t	ca_pciap_base;		/* pci aperature bus base address */
+	uint64_t	ca_pciap_size;		/* pci aperature size (bytes) */
+	uint64_t	ca_pcigart_base;	/* gfx GART bus base address */
+	uint64_t	*ca_pcigart;		/* gfx GART vm address */
+	uint32_t	ca_pcigart_entries;
+	uint32_t	ca_pcigart_start;	/* PCI start index in ca_gart */
+	void		*ca_pcigart_pagemap;
+
+	/* AGP GART convenience values */
+	uint64_t	ca_gfxap_base;		/* gfx aperature bus base address */
+	uint64_t	ca_gfxap_size;		/* gfx aperature size (bytes) */
+	uint64_t	ca_gfxgart_base;	/* gfx GART bus base address */
+	uint64_t	*ca_gfxgart;		/* gfx GART vm address */
+	uint32_t	ca_gfxgart_entries;
+	uint32_t	ca_gfxgart_start;	/* agpgart start index in ca_gart */
+};
+
+/*
+ * Common tioca info shared between kernel and prom
+ *
+ * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES
+ * TO THE PROM VERSION.
+ */
+
+struct tioca_common {
+	struct pcibus_bussoft	ca_common;	/* common pciio header */
+
+	uint32_t		ca_rev;
+	uint32_t		ca_closest_nasid;
+
+	uint64_t		ca_prom_private;
+	uint64_t		ca_kernel_private;
+};
+
+/**
+ * tioca_paddr_to_gart - Convert an SGI coretalk address to a CA GART entry
+ * @paddr: page address to convert
+ *
+ * Convert a system [coretalk] address to a GART entry.  GART entries are
+ * formed using the following:
+ *
+ *     data = ( (1<<63) |  ( (REMAP_NODE_ID << 40) | (MD_CHIPLET_ID << 38) | 
+ * (REMAP_SYS_ADDR) ) >> 12 )
+ *
+ * DATA written to 1 GART TABLE Entry in system memory is remapped system
+ * addr for 1 page 
+ *
+ * The data is for coretalk address format right shifted 12 bits with a
+ * valid bit.
+ *
+ *	GART_TABLE_ENTRY [ 25:0 ]  -- REMAP_SYS_ADDRESS[37:12].
+ *	GART_TABLE_ENTRY [ 27:26 ] -- SHUB MD chiplet id.
+ *	GART_TABLE_ENTRY [ 41:28 ] -- REMAP_NODE_ID.
+ *	GART_TABLE_ENTRY [ 63 ]    -- Valid Bit 
+ */
+static inline u64
+tioca_paddr_to_gart(unsigned long paddr)
+{
+	/*
+	 * We are assuming right now that paddr already has the correct
+	 * format since the address from xtalk_dmaXXX should already have
+	 * NODE_ID, CHIPLET_ID, and SYS_ADDR in the correct locations.
+	 */
+
+	return ((paddr) >> 12) | (1UL << 63);
+}
+
+/**
+ * tioca_physpage_to_gart - Map a host physical page for SGI CA based DMA
+ * @page_addr: system page address to map
+ */
+
+static inline unsigned long
+tioca_physpage_to_gart(uint64_t page_addr)
+{
+	uint64_t coretalk_addr;
+
+	coretalk_addr = PHYS_TO_TIODMA(page_addr);
+	if (!coretalk_addr) {
+		return 0;
+	}
+
+	return tioca_paddr_to_gart(coretalk_addr);
+}
+
+/**
+ * tioca_tlbflush - invalidate cached SGI CA GART TLB entries
+ * @tioca_kernel: CA context 
+ *
+ * Invalidate tlb entries for a given CA GART.  Main complexity is to account
+ * for revA bug.
+ */
+static inline void
+tioca_tlbflush(struct tioca_kernel *tioca_kernel)
+{
+	volatile uint64_t tmp;
+	volatile struct tioca *ca_base;
+	struct tioca_common *tioca_common;
+
+	tioca_common = tioca_kernel->ca_common;
+	ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+
+	/*
+	 * Explicit flushes not needed if GART is in cached mode
+	 */
+	if (tioca_kernel->ca_gart_iscoherent) {
+		if (TIOCA_WAR_ENABLED(PV910244, tioca_common)) {
+			/*
+			 * PV910244:  RevA CA needs explicit flushes.
+			 * Need to put GART into uncached mode before
+			 * flushing otherwise the explicit flush is ignored.
+			 *
+			 * Alternate WAR would be to leave GART cached and
+			 * touch every CL aligned GART entry.
+			 */
+
+			ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
+			ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
+			ca_base->ca_control2 |=
+			    (0x2ull << CA_GART_MEM_PARAM_SHFT);
+			tmp = ca_base->ca_control2;
+		}
+
+		return;
+	}
+
+	/*
+	 * Gart in uncached mode ... need an explicit flush.
+	 */
+
+	ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
+	tmp = ca_base->ca_control2;
+}
+
+extern uint32_t	tioca_gart_found;
+extern int tioca_init_provider(void);
+extern void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern);
+#endif /* _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H */
diff --git a/include/asm-ia64/sn/tiocx.h b/include/asm-ia64/sn/tiocx.h
new file mode 100644
index 0000000..c5447a5
--- /dev/null
+++ b/include/asm-ia64/sn/tiocx.h
@@ -0,0 +1,71 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_TIO_TIOCX_H
+#define _ASM_IA64_SN_TIO_TIOCX_H
+
+#ifdef __KERNEL__
+
+struct cx_id_s {
+	unsigned int part_num;
+	unsigned int mfg_num;
+	int nasid;
+};
+
+struct cx_dev {
+	struct cx_id_s cx_id;
+	void *soft;			/* driver specific */
+	struct hubdev_info *hubdev;
+	struct device dev;
+	struct cx_drv *driver;
+};
+
+struct cx_device_id {
+	unsigned int part_num;
+	unsigned int mfg_num;
+};
+
+struct cx_drv {
+	char *name;
+	const struct cx_device_id *id_table;
+	struct device_driver driver;
+	int (*probe) (struct cx_dev * dev, const struct cx_device_id * id);
+	int (*remove) (struct cx_dev * dev);
+};
+
+/* create DMA address by stripping AS bits */
+#define TIOCX_DMA_ADDR(a) (uint64_t)((uint64_t)(a) & 0xffffcfffffffffUL)
+
+#define TIOCX_TO_TIOCX_DMA_ADDR(a) (uint64_t)(((uint64_t)(a) & 0xfffffffff) |  \
+                                  ((((uint64_t)(a)) & 0xffffc000000000UL) <<2))
+
+#define TIO_CE_ASIC_PARTNUM 0xce00
+#define TIOCX_CORELET 3
+
+/* These are taken from tio_mmr_as.h */
+#define TIO_ICE_FRZ_CFG               TIO_MMR_ADDR_MOD(0x00000000b0008100UL)
+#define TIO_ICE_PMI_TX_CFG            TIO_MMR_ADDR_MOD(0x00000000b000b100UL)
+#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3 TIO_MMR_ADDR_MOD(0x00000000b000be18UL)
+#define TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK 0x000000000000000fUL
+
+#define to_cx_dev(n) container_of(n, struct cx_dev, dev)
+#define to_cx_driver(drv) container_of(drv, struct cx_drv, driver)
+
+extern struct sn_irq_info *tiocx_irq_alloc(nasid_t, int, int, nasid_t, int);
+extern void tiocx_irq_free(struct sn_irq_info *);
+extern int cx_device_unregister(struct cx_dev *);
+extern int cx_device_register(nasid_t, int, int, struct hubdev_info *);
+extern int cx_driver_unregister(struct cx_drv *);
+extern int cx_driver_register(struct cx_drv *);
+extern uint64_t tiocx_dma_addr(uint64_t addr);
+extern uint64_t tiocx_swin_base(int nasid);
+extern void tiocx_mmr_store(int nasid, uint64_t offset, uint64_t value);
+extern uint64_t tiocx_mmr_load(int nasid, uint64_t offset);
+
+#endif				//  __KERNEL__
+#endif				// _ASM_IA64_SN_TIO_TIOCX__
diff --git a/include/asm-ia64/sn/types.h b/include/asm-ia64/sn/types.h
index 586ed47..8e04ee2 100644
--- a/include/asm-ia64/sn/types.h
+++ b/include/asm-ia64/sn/types.h
@@ -16,7 +16,8 @@
 typedef signed char	partid_t;	/* partition ID type */
 typedef unsigned int    moduleid_t;     /* user-visible module number type */
 typedef unsigned int    cmoduleid_t;    /* kernel compact module id type */
-typedef signed char     slabid_t;
+typedef unsigned char	slotid_t;	/* slot (blade) within module */
+typedef unsigned char	slabid_t;	/* slab (asic) within slot */
 typedef u64 nic_t;
 typedef unsigned long iopaddr_t;
 typedef unsigned long paddr_t;
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
new file mode 100644
index 0000000..9902185
--- /dev/null
+++ b/include/asm-ia64/sn/xp.h
@@ -0,0 +1,436 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+/*
+ * External Cross Partition (XP) structures and defines.
+ */
+
+
+#ifndef _ASM_IA64_SN_XP_H
+#define _ASM_IA64_SN_XP_H
+
+
+#include <linux/version.h>
+#include <linux/cache.h>
+#include <linux/hardirq.h>
+#include <asm/sn/types.h>
+#include <asm/sn/bte.h>
+
+
+#ifdef USE_DBUG_ON
+#define DBUG_ON(condition)	BUG_ON(condition)
+#else
+#define DBUG_ON(condition)
+#endif
+
+
+/*
+ * Define the maximum number of logically defined partitions the system
+ * can support. It is constrained by the maximum number of hardware
+ * partitionable regions. The term 'region' in this context refers to the
+ * minimum number of nodes that can comprise an access protection grouping.
+ * The access protection is in regards to memory, IPI and IOI.
+ *
+ * The maximum number of hardware partitionable regions is equal to the
+ * maximum number of nodes in the entire system divided by the minimum number
+ * of nodes that comprise an access protection grouping.
+ */
+#define XP_MAX_PARTITIONS	64
+
+
+/*
+ * Define the number of u64s required to represent all the C-brick nasids
+ * as a bitmap.  The cross-partition kernel modules deal only with
+ * C-brick nasids, thus the need for bitmaps which don't account for
+ * odd-numbered (non C-brick) nasids.
+ */
+#define XP_MAX_PHYSNODE_ID	(MAX_PHYSNODE_ID / 2)
+#define XP_NASID_MASK_BYTES	((XP_MAX_PHYSNODE_ID + 7) / 8)
+#define XP_NASID_MASK_WORDS	((XP_MAX_PHYSNODE_ID + 63) / 64)
+
+
+/*
+ * Wrapper for bte_copy() that should it return a failure status will retry
+ * the bte_copy() once in the hope that the failure was due to a temporary
+ * aberration (i.e., the link going down temporarily).
+ *
+ * See bte_copy for definition of the input parameters.
+ *
+ * Note: xp_bte_copy() should never be called while holding a spinlock.
+ */
+static inline bte_result_t
+xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
+{
+	bte_result_t ret;
+
+
+	ret = bte_copy(src, dest, len, mode, notification);
+
+	if (ret != BTE_SUCCESS) {
+		if (!in_interrupt()) {
+			cond_resched();
+		}
+		ret = bte_copy(src, dest, len, mode, notification);
+	}
+
+	return ret;
+}
+
+
+/*
+ * XPC establishes channel connections between the local partition and any
+ * other partition that is currently up. Over these channels, kernel-level
+ * `users' can communicate with their counterparts on the other partitions.
+ *
+ * The maxinum number of channels is limited to eight. For performance reasons,
+ * the internal cross partition structures require sixteen bytes per channel,
+ * and eight allows all of this interface-shared info to fit in one cache line.
+ *
+ * XPC_NCHANNELS reflects the total number of channels currently defined.
+ * If the need for additional channels arises, one can simply increase
+ * XPC_NCHANNELS accordingly. If the day should come where that number
+ * exceeds the MAXIMUM number of channels allowed (eight), then one will need
+ * to make changes to the XPC code to allow for this.
+ */
+#define XPC_MEM_CHANNEL		0	/* memory channel number */
+#define	XPC_NET_CHANNEL		1	/* network channel number */
+
+#define	XPC_NCHANNELS		2	/* #of defined channels */
+#define XPC_MAX_NCHANNELS	8	/* max #of channels allowed */
+
+#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
+#error	XPC_NCHANNELS exceeds MAXIMUM allowed.
+#endif
+
+
+/*
+ * The format of an XPC message is as follows:
+ *
+ *      +-------+--------------------------------+
+ *      | flags |////////////////////////////////|
+ *      +-------+--------------------------------+
+ *      |             message #                  |
+ *      +----------------------------------------+
+ *      |     payload (user-defined message)     |
+ *      |                                        |
+ *         		:
+ *      |                                        |
+ *      +----------------------------------------+
+ *
+ * The size of the payload is defined by the user via xpc_connect(). A user-
+ * defined message resides in the payload area.
+ *
+ * The user should have no dealings with the message header, but only the
+ * message's payload. When a message entry is allocated (via xpc_allocate())
+ * a pointer to the payload area is returned and not the actual beginning of
+ * the XPC message. The user then constructs a message in the payload area
+ * and passes that pointer as an argument on xpc_send() or xpc_send_notify().
+ *
+ * The size of a message entry (within a message queue) must be a cacheline
+ * sized multiple in order to facilitate the BTE transfer of messages from one
+ * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
+ * that wants to fit as many msg entries as possible in a given memory size
+ * (e.g. a memory page).
+ */
+struct xpc_msg {
+	u8 flags;		/* FOR XPC INTERNAL USE ONLY */
+	u8 reserved[7];		/* FOR XPC INTERNAL USE ONLY */
+	s64 number;		/* FOR XPC INTERNAL USE ONLY */
+
+	u64 payload;		/* user defined portion of message */
+};
+
+
+#define XPC_MSG_PAYLOAD_OFFSET	(u64) (&((struct xpc_msg *)0)->payload)
+#define XPC_MSG_SIZE(_payload_size) \
+		L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))
+
+
+/*
+ * Define the return values and values passed to user's callout functions.
+ * (It is important to add new value codes at the end just preceding
+ * xpcUnknownReason, which must have the highest numerical value.)
+ */
+enum xpc_retval {
+	xpcSuccess = 0,
+
+	xpcNotConnected,	/*  1: channel is not connected */
+	xpcConnected,		/*  2: channel connected (opened) */
+	xpcRETIRED1,		/*  3: (formerly xpcDisconnected) */
+
+	xpcMsgReceived,		/*  4: message received */
+	xpcMsgDelivered,	/*  5: message delivered and acknowledged */
+
+	xpcRETIRED2,		/*  6: (formerly xpcTransferFailed) */
+
+	xpcNoWait,		/*  7: operation would require wait */
+	xpcRetry,		/*  8: retry operation */
+	xpcTimeout,		/*  9: timeout in xpc_allocate_msg_wait() */
+	xpcInterrupted,		/* 10: interrupted wait */
+
+	xpcUnequalMsgSizes,	/* 11: message size disparity between sides */
+	xpcInvalidAddress,	/* 12: invalid address */
+
+	xpcNoMemory,		/* 13: no memory available for XPC structures */
+	xpcLackOfResources,	/* 14: insufficient resources for operation */
+	xpcUnregistered,	/* 15: channel is not registered */
+	xpcAlreadyRegistered,	/* 16: channel is already registered */
+
+	xpcPartitionDown,	/* 17: remote partition is down */
+	xpcNotLoaded,		/* 18: XPC module is not loaded */
+	xpcUnloading,		/* 19: this side is unloading XPC module */
+
+	xpcBadMagic,		/* 20: XPC MAGIC string not found */
+
+	xpcReactivating,	/* 21: remote partition was reactivated */
+
+	xpcUnregistering,	/* 22: this side is unregistering channel */
+	xpcOtherUnregistering,	/* 23: other side is unregistering channel */
+
+	xpcCloneKThread,	/* 24: cloning kernel thread */
+	xpcCloneKThreadFailed,	/* 25: cloning kernel thread failed */
+
+	xpcNoHeartbeat,		/* 26: remote partition has no heartbeat */
+
+	xpcPioReadError,	/* 27: PIO read error */
+	xpcPhysAddrRegFailed,	/* 28: registration of phys addr range failed */
+
+	xpcBteDirectoryError,	/* 29: maps to BTEFAIL_DIR */
+	xpcBtePoisonError,	/* 30: maps to BTEFAIL_POISON */
+	xpcBteWriteError,	/* 31: maps to BTEFAIL_WERR */
+	xpcBteAccessError,	/* 32: maps to BTEFAIL_ACCESS */
+	xpcBtePWriteError,	/* 33: maps to BTEFAIL_PWERR */
+	xpcBtePReadError,	/* 34: maps to BTEFAIL_PRERR */
+	xpcBteTimeOutError,	/* 35: maps to BTEFAIL_TOUT */
+	xpcBteXtalkError,	/* 36: maps to BTEFAIL_XTERR */
+	xpcBteNotAvailable,	/* 37: maps to BTEFAIL_NOTAVAIL */
+	xpcBteUnmappedError,	/* 38: unmapped BTEFAIL_ error */
+
+	xpcBadVersion,		/* 39: bad version number */
+	xpcVarsNotSet,		/* 40: the XPC variables are not set up */
+	xpcNoRsvdPageAddr,	/* 41: unable to get rsvd page's phys addr */
+	xpcInvalidPartid,	/* 42: invalid partition ID */
+	xpcLocalPartid,		/* 43: local partition ID */
+
+	xpcUnknownReason	/* 44: unknown reason -- must be last in list */
+};
+
+
+/*
+ * Define the callout function types used by XPC to update the user on
+ * connection activity and state changes (via the user function registered by
+ * xpc_connect()) and to notify them of messages received and delivered (via
+ * the user function registered by xpc_send_notify()).
+ *
+ * The two function types are xpc_channel_func and xpc_notify_func and
+ * both share the following arguments, with the exception of "data", which
+ * only xpc_channel_func has.
+ *
+ * Arguments:
+ *
+ *	reason - reason code. (See following table.)
+ *	partid - partition ID associated with condition.
+ *	ch_number - channel # associated with condition.
+ *	data - pointer to optional data. (See following table.)
+ *	key - pointer to optional user-defined value provided as the "key"
+ *	      argument to xpc_connect() or xpc_send_notify().
+ *
+ * In the following table the "Optional Data" column applies to callouts made
+ * to functions registered by xpc_connect(). A "NA" in that column indicates
+ * that this reason code can be passed to functions registered by
+ * xpc_send_notify() (i.e. they don't have data arguments).
+ *
+ * Also, the first three reason codes in the following table indicate
+ * success, whereas the others indicate failure. When a failure reason code
+ * is received, one can assume that the channel is not connected.
+ *
+ *
+ * Reason Code          | Cause                          | Optional Data
+ * =====================+================================+=====================
+ * xpcConnected         | connection has been established| max #of entries
+ *                      | to the specified partition on  | allowed in message
+ *                      | the specified channel          | queue
+ * ---------------------+--------------------------------+---------------------
+ * xpcMsgReceived       | an XPC message arrived from    | address of payload
+ *                      | the specified partition on the |
+ *                      | specified channel              | [the user must call
+ *                      |                                | xpc_received() when
+ *                      |                                | finished with the
+ *                      |                                | payload]
+ * ---------------------+--------------------------------+---------------------
+ * xpcMsgDelivered      | notification that the message  | NA
+ *                      | was delivered to the intended  |
+ *                      | recipient and that they have   |
+ *                      | acknowledged its receipt by    |
+ *                      | calling xpc_received()         |
+ * =====================+================================+=====================
+ * xpcUnequalMsgSizes   | can't connect to the specified | NULL
+ *                      | partition on the specified     |
+ *                      | channel because of mismatched  |
+ *                      | message sizes                  |
+ * ---------------------+--------------------------------+---------------------
+ * xpcNoMemory          | insufficient memory avaiable   | NULL
+ *                      | to allocate message queue      |
+ * ---------------------+--------------------------------+---------------------
+ * xpcLackOfResources   | lack of resources to create    | NULL
+ *                      | the necessary kthreads to      |
+ *                      | support the channel            |
+ * ---------------------+--------------------------------+---------------------
+ * xpcUnregistering     | this side's user has           | NULL or NA
+ *                      | unregistered by calling        |
+ *                      | xpc_disconnect()               |
+ * ---------------------+--------------------------------+---------------------
+ * xpcOtherUnregistering| the other side's user has      | NULL or NA
+ *                      | unregistered by calling        |
+ *                      | xpc_disconnect()               |
+ * ---------------------+--------------------------------+---------------------
+ * xpcNoHeartbeat       | the other side's XPC is no     | NULL or NA
+ *                      | longer heartbeating            |
+ *                      |                                |
+ * ---------------------+--------------------------------+---------------------
+ * xpcUnloading         | this side's XPC module is      | NULL or NA
+ *                      | being unloaded                 |
+ *                      |                                |
+ * ---------------------+--------------------------------+---------------------
+ * xpcOtherUnloading    | the other side's XPC module is | NULL or NA
+ *                      | is being unloaded              |
+ *                      |                                |
+ * ---------------------+--------------------------------+---------------------
+ * xpcPioReadError      | xp_nofault_PIOR() returned an  | NULL or NA
+ *                      | error while sending an IPI     |
+ *                      |                                |
+ * ---------------------+--------------------------------+---------------------
+ * xpcInvalidAddress    | the address either received or | NULL or NA
+ *                      | sent by the specified partition|
+ *                      | is invalid                     |
+ * ---------------------+--------------------------------+---------------------
+ * xpcBteNotAvailable   | attempt to pull data from the  | NULL or NA
+ * xpcBtePoisonError    | specified partition over the   |
+ * xpcBteWriteError     | specified channel via a        |
+ * xpcBteAccessError    | bte_copy() failed              |
+ * xpcBteTimeOutError   |                                |
+ * xpcBteXtalkError     |                                |
+ * xpcBteDirectoryError |                                |
+ * xpcBteGenericError   |                                |
+ * xpcBteUnmappedError  |                                |
+ * ---------------------+--------------------------------+---------------------
+ * xpcUnknownReason     | the specified channel to the   | NULL or NA
+ *                      | specified partition was        |
+ *                      | unavailable for unknown reasons|
+ * =====================+================================+=====================
+ */
+
+typedef void (*xpc_channel_func)(enum xpc_retval reason, partid_t partid,
+		int ch_number, void *data, void *key);
+
+typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
+		int ch_number, void *key);
+
+
+/*
+ * The following is a registration entry. There is a global array of these,
+ * one per channel. It is used to record the connection registration made
+ * by the users of XPC. As long as a registration entry exists, for any
+ * partition that comes up, XPC will attempt to establish a connection on
+ * that channel. Notification that a connection has been made will occur via
+ * the xpc_channel_func function.
+ *
+ * The 'func' field points to the function to call when aynchronous
+ * notification is required for such events as: a connection established/lost,
+ * or an incomming message received, or an error condition encountered. A
+ * non-NULL 'func' field indicates that there is an active registration for
+ * the channel.
+ */
+struct xpc_registration {
+	struct semaphore sema;
+	xpc_channel_func func;		/* function to call */
+	void *key;			/* pointer to user's key */
+	u16 nentries;			/* #of msg entries in local msg queue */
+	u16 msg_size;			/* message queue's message size */
+	u32 assigned_limit;		/* limit on #of assigned kthreads */
+	u32 idle_limit;			/* limit on #of idle kthreads */
+} ____cacheline_aligned;
+
+
+#define XPC_CHANNEL_REGISTERED(_c)	(xpc_registrations[_c].func != NULL)
+
+
+/* the following are valid xpc_allocate() flags */
+#define XPC_WAIT	0		/* wait flag */
+#define XPC_NOWAIT	1		/* no wait flag */
+
+
+struct xpc_interface {
+	void (*connect)(int);
+	void (*disconnect)(int);
+	enum xpc_retval (*allocate)(partid_t, int, u32, void **);
+	enum xpc_retval (*send)(partid_t, int, void *);
+	enum xpc_retval (*send_notify)(partid_t, int, void *,
+						xpc_notify_func, void *);
+	void (*received)(partid_t, int, void *);
+	enum xpc_retval (*partid_to_nasids)(partid_t, void *);
+};
+
+
+extern struct xpc_interface xpc_interface;
+
+extern void xpc_set_interface(void (*)(int),
+		void (*)(int),
+		enum xpc_retval (*)(partid_t, int, u32, void **),
+		enum xpc_retval (*)(partid_t, int, void *),
+		enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func,
+								void *),
+		void (*)(partid_t, int, void *),
+		enum xpc_retval (*)(partid_t, void *));
+extern void xpc_clear_interface(void);
+
+
+extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,
+						u16, u32, u32);
+extern void xpc_disconnect(int);
+
+static inline enum xpc_retval
+xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
+{
+	return xpc_interface.allocate(partid, ch_number, flags, payload);
+}
+
+static inline enum xpc_retval
+xpc_send(partid_t partid, int ch_number, void *payload)
+{
+	return xpc_interface.send(partid, ch_number, payload);
+}
+
+static inline enum xpc_retval
+xpc_send_notify(partid_t partid, int ch_number, void *payload,
+			xpc_notify_func func, void *key)
+{
+	return xpc_interface.send_notify(partid, ch_number, payload, func, key);
+}
+
+static inline void
+xpc_received(partid_t partid, int ch_number, void *payload)
+{
+	return xpc_interface.received(partid, ch_number, payload);
+}
+
+static inline enum xpc_retval
+xpc_partid_to_nasids(partid_t partid, void *nasids)
+{
+	return xpc_interface.partid_to_nasids(partid, nasids);
+}
+
+
+extern u64 xp_nofault_PIOR_target;
+extern int xp_nofault_PIOR(void *);
+extern int xp_error_PIOR(void);
+
+
+#endif /* _ASM_IA64_SN_XP_H */
+
diff --git a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h
index ce46eae..95f69b1 100644
--- a/include/asm-m32r/signal.h
+++ b/include/asm-m32r/signal.h
@@ -114,34 +114,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-m68k/bug.h b/include/asm-m68k/bug.h
index 3e1d226..072ce27 100644
--- a/include/asm-m68k/bug.h
+++ b/include/asm-m68k/bug.h
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 #ifndef CONFIG_SUN3
 #define BUG() do { \
@@ -22,6 +23,8 @@
 #endif
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h
index 6681bb6..a0cdf90 100644
--- a/include/asm-m68k/signal.h
+++ b/include/asm-m68k/signal.h
@@ -105,42 +105,20 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
 	unsigned long sa_flags;
-	void (*sa_restorer)(void);
+	__sigrestore_t sa_restorer;
 };
 
 struct sigaction {
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
-	void (*sa_restorer)(void);
+	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
 
diff --git a/include/asm-m68knommu/MC68328.h b/include/asm-m68knommu/MC68328.h
index 4f5a984..a337e56 100644
--- a/include/asm-m68knommu/MC68328.h
+++ b/include/asm-m68knommu/MC68328.h
@@ -993,7 +993,7 @@
   volatile unsigned short int pad1;
   volatile unsigned short int pad2;
   volatile unsigned short int pad3;
-} m68328_uart __attribute__((packed));
+} __attribute__((packed)) m68328_uart;
 
 
 /**********
diff --git a/include/asm-m68knommu/MC68EZ328.h b/include/asm-m68knommu/MC68EZ328.h
index 801933d..69b7f91 100644
--- a/include/asm-m68knommu/MC68EZ328.h
+++ b/include/asm-m68knommu/MC68EZ328.h
@@ -815,7 +815,7 @@
   volatile unsigned short int nipr;
   volatile unsigned short int pad1;
   volatile unsigned short int pad2;
-} m68328_uart __attribute__((packed));
+} __attribute__((packed)) m68328_uart;
 
 
 /**********
diff --git a/include/asm-m68knommu/MC68VZ328.h b/include/asm-m68knommu/MC68VZ328.h
index df74322..2b9bf62 100644
--- a/include/asm-m68knommu/MC68VZ328.h
+++ b/include/asm-m68knommu/MC68VZ328.h
@@ -909,7 +909,7 @@
   volatile unsigned short int nipr;
   volatile unsigned short int hmark;
   volatile unsigned short int unused;
-} m68328_uart __attribute__((packed));
+} __attribute__((packed)) m68328_uart;
 
 
 
diff --git a/include/asm-m68knommu/signal.h b/include/asm-m68knommu/signal.h
index 486cbb0..1d13187 100644
--- a/include/asm-m68knommu/signal.h
+++ b/include/asm-m68knommu/signal.h
@@ -105,29 +105,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h
index eb94bb9..3f594b4 100644
--- a/include/asm-mips/bug.h
+++ b/include/asm-mips/bug.h
@@ -3,12 +3,14 @@
 
 #include <asm/break.h>
 
+#ifdef CONFIG_BUG
+#define HAVE_ARCH_BUG
 #define BUG()								\
 do {									\
 	__asm__ __volatile__("break %0" : : "i" (BRK_BUG));		\
 } while (0)
+#endif
 
-#define HAVE_ARCH_BUG
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h
index 2b458f9..3c0d840 100644
--- a/include/asm-mips/errno.h
+++ b/include/asm-mips/errno.h
@@ -115,6 +115,10 @@
 #define	EKEYREVOKED	163	/* Key has been revoked */
 #define	EKEYREJECTED	164	/* Key was rejected by service */
 
+/* for robust mutexes */
+#define	EOWNERDEAD	165	/* Owner died */
+#define	ENOTRECOVERABLE	166	/* State not recoverable */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 #ifdef __KERNEL__
diff --git a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
index 8ddd3c9..a0e26e6 100644
--- a/include/asm-mips/siginfo.h
+++ b/include/asm-mips/siginfo.h
@@ -11,8 +11,6 @@
 
 #include <linux/config.h>
 
-#define SIGEV_HEAD_SIZE	(sizeof(long) + 2*sizeof(int))
-#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE-SIGEV_HEAD_SIZE) / sizeof(int))
 #undef __ARCH_SI_TRAPNO	/* exception code needs to fill this ...  */
 
 #define HAVE_ARCH_SIGINFO_T
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
index 994987d..f2c470f 100644
--- a/include/asm-mips/signal.h
+++ b/include/asm-mips/signal.h
@@ -98,34 +98,12 @@
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x02000000
-
-#endif /* __KERNEL__ */
-
 #define SIG_BLOCK	1	/* for blocking signals */
 #define SIG_UNBLOCK	2	/* for unblocking signals */
 #define SIG_SETMASK	3	/* for setting the signal mask */
 #define SIG_SETMASK32	256	/* Goodie from SGI for BSD compatibility:
 				   set only the low 32 bit of the sigset.  */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-/* Fake signal functions */
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 struct sigaction {
 	unsigned int	sa_flags;
diff --git a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h
index e72f6e2..695588d 100644
--- a/include/asm-parisc/bug.h
+++ b/include/asm-parisc/bug.h
@@ -1,12 +1,14 @@
 #ifndef _PARISC_BUG_H
 #define _PARISC_BUG_H
 
+#ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
 	dump_stack(); \
 	panic("BUG!"); \
 } while (0)
+#endif
 
 #include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-parisc/errno.h b/include/asm-parisc/errno.h
index a10f109..08464c4 100644
--- a/include/asm-parisc/errno.h
+++ b/include/asm-parisc/errno.h
@@ -115,5 +115,9 @@
 #define ENOTSUP		252	/* Function not implemented (POSIX.4 / HPUX) */
 #define ECANCELLED	253	/* aio request was canceled before complete (POSIX.4 / HPUX) */
 
+/* for robust mutexes */
+#define EOWNERDEAD	254	/* Owner died */
+#define ENOTRECOVERABLE	255	/* State not recoverable */
+
 
 #endif
diff --git a/include/asm-parisc/floppy.h b/include/asm-parisc/floppy.h
index 47f53df..ca3aed7 100644
--- a/include/asm-parisc/floppy.h
+++ b/include/asm-parisc/floppy.h
@@ -235,7 +235,7 @@
 	return 0;
 }
 
-struct fd_routine_l {
+static struct fd_routine_l {
 	int (*_request_dma)(unsigned int dmanr, const char * device_id);
 	void (*_free_dma)(unsigned int dmanr);
 	int (*_get_dma_residue)(unsigned int dummy);
diff --git a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h
index 358f577..25cb23e 100644
--- a/include/asm-parisc/signal.h
+++ b/include/asm-parisc/signal.h
@@ -89,17 +89,6 @@
 #define _NSIG_BPW	BITS_PER_LONG
 #define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
 
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-
 #endif /* __KERNEL__ */
 
 #define SIG_BLOCK          0	/* for blocking signals */
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
index 8a08423..c1b5bde 100644
--- a/include/asm-parisc/uaccess.h
+++ b/include/asm-parisc/uaccess.h
@@ -24,7 +24,7 @@
 
 /*
  * Note that since kernel addresses are in a separate address space on
- * parisc, we don't need to do anything for access_ok() or verify_area().
+ * parisc, we don't need to do anything for access_ok().
  * We just let the page fault handler do the right thing. This also means
  * that put_user is the same as __put_user, etc.
  */
diff --git a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h
index e99c6cb..8b34fd6 100644
--- a/include/asm-ppc/bug.h
+++ b/include/asm-ppc/bug.h
@@ -14,6 +14,7 @@
  */
 #define BUG_WARNING_TRAP	0x1000000
 
+#ifdef CONFIG_BUG
 #define BUG() do {							 \
 	__asm__ __volatile__(						 \
 		"1:	twi 31,0,0\n"					 \
@@ -50,6 +51,8 @@
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG_ON
 #define HAVE_ARCH_WARN_ON
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-ppc/hydra.h b/include/asm-ppc/hydra.h
index 1134431..833a8af 100644
--- a/include/asm-ppc/hydra.h
+++ b/include/asm-ppc/hydra.h
@@ -51,7 +51,7 @@
     char OpenPIC[0x40000];
 };
 
-extern volatile struct Hydra *Hydra;
+extern volatile struct Hydra __iomem *Hydra;
 
 
     /*
diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
index 78e9be6..ffa4234 100644
--- a/include/asm-ppc/pci-bridge.h
+++ b/include/asm-ppc/pci-bridge.h
@@ -12,7 +12,7 @@
  * pci_io_base returns the memory address at which you can access
  * the I/O space for PCI bus number `bus' (or NULL on error).
  */
-extern void *pci_bus_io_base(unsigned int bus);
+extern void __iomem *pci_bus_io_base(unsigned int bus);
 extern unsigned long pci_bus_io_base_phys(unsigned int bus);
 extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
 
@@ -48,7 +48,7 @@
 	int last_busno;
 	int bus_offset;
 
-	void *io_base_virt;
+	void __iomem *io_base_virt;
 	unsigned long io_base_phys;
 
 	/* Some machines (PReP) have a non 1:1 mapping of
diff --git a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
index 639b690..8beb162 100644
--- a/include/asm-ppc/pmac_feature.h
+++ b/include/asm-ppc/pmac_feature.h
@@ -316,6 +316,9 @@
 extern void pmac_suspend_agp_for_card(struct pci_dev *dev);
 extern void pmac_resume_agp_for_card(struct pci_dev *dev);
 
+/* Used by the via-pmu driver for suspend/resume
+ */
+extern void pmac_tweak_clock_spreading(int enable);
 
 /*
  * The part below is for use by macio_asic.c only, do not rely
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index e70c25f..45c5e6f 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -305,6 +305,7 @@
 #define ESR_PIL		0x08000000	/* Program Exception - Illegal */
 #define ESR_PPR		0x04000000	/* Program Exception - Priveleged */
 #define ESR_PTR		0x02000000	/* Program Exception - Trap */
+#define ESR_FP		0x01000000	/* Floating Point Operation */
 #define ESR_DST		0x00800000	/* Storage Exception - Data miss */
 #define ESR_DIZ		0x00400000	/* Storage Exception - Zone fault */
 #define ESR_ST		0x00800000	/* Store Operation */
diff --git a/include/asm-ppc/sigcontext.h b/include/asm-ppc/sigcontext.h
index fc5e358..f82dccc 100644
--- a/include/asm-ppc/sigcontext.h
+++ b/include/asm-ppc/sigcontext.h
@@ -9,7 +9,7 @@
 	int		signal;
 	unsigned long	handler;
 	unsigned long	oldmask;
-	struct pt_regs 	*regs;
+	struct pt_regs 	__user *regs;
 };
 
 #endif
diff --git a/include/asm-ppc/signal.h b/include/asm-ppc/signal.h
index 8cc8b88..caf6ede 100644
--- a/include/asm-ppc/signal.h
+++ b/include/asm-ppc/signal.h
@@ -99,34 +99,8 @@
 
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
-#ifdef __KERNEL__
 
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif /* __KERNEL__ */
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 struct old_sigaction {
 	__sighandler_t sa_handler;
diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h
index 802338e..3871e25 100644
--- a/include/asm-ppc64/a.out.h
+++ b/include/asm-ppc64/a.out.h
@@ -1,8 +1,6 @@
 #ifndef __PPC64_A_OUT_H__
 #define __PPC64_A_OUT_H__
 
-#include <asm/ppcdebug.h>
-
 /*
  * c 2001 PPC 64 Team, IBM Corp
  *
diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h
index db31dd2..169868f 100644
--- a/include/asm-ppc64/bug.h
+++ b/include/asm-ppc64/bug.h
@@ -26,6 +26,8 @@
  */
 #define BUG_WARNING_TRAP	0x1000000
 
+#ifdef CONFIG_BUG
+
 #define BUG() do {							 \
 	__asm__ __volatile__(						 \
 		"1:	twi 31,0,0\n"					 \
@@ -55,11 +57,12 @@
 		    "i" (__FILE__), "i" (__FUNCTION__));	\
 } while (0)
 
-#endif
-
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG_ON
 #define HAVE_ARCH_WARN_ON
+#endif
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
index 8457d90..6c42d61 100644
--- a/include/asm-ppc64/elf.h
+++ b/include/asm-ppc64/elf.h
@@ -229,9 +229,13 @@
 
 /*
  * An executable for which elf_read_implies_exec() returns TRUE will
- * have the READ_IMPLIES_EXEC personality flag set automatically.
+ * have the READ_IMPLIES_EXEC personality flag set automatically. This
+ * is only required to work around bugs in old 32bit toolchains. Since
+ * the 64bit ABI has never had these issues dont enable the workaround
+ * even if we have an executable stack.
  */
-#define elf_read_implies_exec(ex, exec_stk)	(exec_stk != EXSTACK_DISABLE_X)
+#define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
+		(exec_stk != EXSTACK_DISABLE_X) : 0)
 
 #endif
 
diff --git a/include/asm-ppc64/imalloc.h b/include/asm-ppc64/imalloc.h
new file mode 100644
index 0000000..3a45e91
--- /dev/null
+++ b/include/asm-ppc64/imalloc.h
@@ -0,0 +1,24 @@
+#ifndef _PPC64_IMALLOC_H
+#define _PPC64_IMALLOC_H
+
+/*
+ * Define the address range of the imalloc VM area.
+ */
+#define PHBS_IO_BASE  	  IOREGIONBASE
+#define IMALLOC_BASE      (IOREGIONBASE + 0x80000000ul)	/* Reserve 2 gigs for PHBs */
+#define IMALLOC_END       (IOREGIONBASE + EADDR_MASK)
+
+
+/* imalloc region types */
+#define IM_REGION_UNUSED	0x1
+#define IM_REGION_SUBSET	0x2
+#define IM_REGION_EXISTS	0x4
+#define IM_REGION_OVERLAP	0x8
+#define IM_REGION_SUPERSET	0x10
+
+extern struct vm_struct * im_get_free_area(unsigned long size);
+extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
+			int region_type);
+unsigned long im_free(void *addr);
+
+#endif /* _PPC64_IMALLOC_H */
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
index 188987e..c78282a 100644
--- a/include/asm-ppc64/mmu.h
+++ b/include/asm-ppc64/mmu.h
@@ -15,19 +15,10 @@
 
 #include <linux/config.h>
 #include <asm/page.h>
-#include <linux/stringify.h>
 
-#ifndef __ASSEMBLY__
-
-/* Time to allow for more things here */
-typedef unsigned long mm_context_id_t;
-typedef struct {
-	mm_context_id_t id;
-#ifdef CONFIG_HUGETLB_PAGE
-	pgd_t *huge_pgdir;
-	u16 htlb_segs; /* bitmask */
-#endif
-} mm_context_t;
+/*
+ * Segment table
+ */
 
 #define STE_ESID_V	0x80
 #define STE_ESID_KS	0x20
@@ -36,15 +27,48 @@
 
 #define STE_VSID_SHIFT	12
 
-struct stab_entry {
-	unsigned long esid_data;
-	unsigned long vsid_data;
-};
+/* Location of cpu0's segment table */
+#define STAB0_PAGE	0x9
+#define STAB0_PHYS_ADDR	(STAB0_PAGE<<PAGE_SHIFT)
+#define STAB0_VIRT_ADDR	(KERNELBASE+STAB0_PHYS_ADDR)
 
-/* Hardware Page Table Entry */
+/*
+ * SLB
+ */
+
+#define SLB_NUM_BOLTED		3
+#define SLB_CACHE_ENTRIES	8
+
+/* Bits in the SLB ESID word */
+#define SLB_ESID_V		ASM_CONST(0x0000000008000000) /* valid */
+
+/* Bits in the SLB VSID word */
+#define SLB_VSID_SHIFT		12
+#define SLB_VSID_KS		ASM_CONST(0x0000000000000800)
+#define SLB_VSID_KP		ASM_CONST(0x0000000000000400)
+#define SLB_VSID_N		ASM_CONST(0x0000000000000200) /* no-execute */
+#define SLB_VSID_L		ASM_CONST(0x0000000000000100) /* largepage 16M */
+#define SLB_VSID_C		ASM_CONST(0x0000000000000080) /* class */
+
+#define SLB_VSID_KERNEL		(SLB_VSID_KP|SLB_VSID_C)
+#define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS)
+
+/*
+ * Hash table
+ */
 
 #define HPTES_PER_GROUP 8
 
+/* Values for PP (assumes Ks=0, Kp=1) */
+/* pp0 will always be 0 for linux     */
+#define PP_RWXX	0	/* Supervisor read/write, User none */
+#define PP_RWRX 1	/* Supervisor read/write, User read */
+#define PP_RWRW 2	/* Supervisor read/write, User read/write */
+#define PP_RXRX 3	/* Supervisor read,       User read */
+
+#ifndef __ASSEMBLY__
+
+/* Hardware Page Table Entry */
 typedef struct {
 	unsigned long avpn:57; /* vsid | api == avpn  */
 	unsigned long :     2; /* Software use */
@@ -90,14 +114,6 @@
 	} dw1;
 } HPTE; 
 
-/* Values for PP (assumes Ks=0, Kp=1) */
-/* pp0 will always be 0 for linux     */
-#define PP_RWXX	0	/* Supervisor read/write, User none */
-#define PP_RWRX 1	/* Supervisor read/write, User read */
-#define PP_RWRW 2	/* Supervisor read/write, User read/write */
-#define PP_RXRX 3	/* Supervisor read,       User read */
-
-
 extern HPTE *		htab_address;
 extern unsigned long	htab_hash_mask;
 
@@ -174,31 +190,70 @@
 
 extern void htab_finish_init(void);
 
+extern void hpte_init_native(void);
+extern void hpte_init_lpar(void);
+extern void hpte_init_iSeries(void);
+
+extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+				     unsigned long va, unsigned long prpn,
+				     int secondary, unsigned long hpteflags,
+				     int bolted, int large);
+extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+			       unsigned long prpn, int secondary,
+			       unsigned long hpteflags, int bolted, int large);
+
 #endif /* __ASSEMBLY__ */
 
 /*
- * Location of cpu0's segment table
+ * VSID allocation
+ *
+ * We first generate a 36-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID, for user addresses it is:
+ *	(context << 15) | (esid & 0x7fff)
+ *
+ * The two forms are distinguishable because the top bit is 0 for user
+ * addresses, whereas the top two bits are 1 for kernel addresses.
+ * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
+ * now.
+ *
+ * The proto-VSIDs are then scrambled into real VSIDs with the
+ * multiplicative hash:
+ *
+ *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
+ *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
+ *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
+ *
+ * This scramble is only well defined for proto-VSIDs below
+ * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
+ * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
+ * Because the modulus is 2^n-1 we can compute it efficiently without
+ * a divide or extra multiply (see below).
+ *
+ * This scheme has several advantages over older methods:
+ *
+ * 	- We have VSIDs allocated for every kernel address
+ * (i.e. everything above 0xC000000000000000), except the very top
+ * segment, which simplifies several things.
+ *
+ * 	- We allow for 15 significant bits of ESID and 20 bits of
+ * context for user addresses.  i.e. 8T (43 bits) of address space for
+ * up to 1M contexts (although the page table structure and context
+ * allocation will need changes to take advantage of this).
+ *
+ * 	- The scramble function gives robust scattering in the hash
+ * table (at least based on some initial results).  The previous
+ * method was more susceptible to pathological cases giving excessive
+ * hash collisions.
  */
-#define STAB0_PAGE	0x9
-#define STAB0_PHYS_ADDR	(STAB0_PAGE<<PAGE_SHIFT)
-#define STAB0_VIRT_ADDR	(KERNELBASE+STAB0_PHYS_ADDR)
-
-#define SLB_NUM_BOLTED		3
-#define SLB_CACHE_ENTRIES	8
-
-/* Bits in the SLB ESID word */
-#define SLB_ESID_V		0x0000000008000000	/* entry is valid */
-
-/* Bits in the SLB VSID word */
-#define SLB_VSID_SHIFT		12
-#define SLB_VSID_KS		0x0000000000000800
-#define SLB_VSID_KP		0x0000000000000400
-#define SLB_VSID_N		0x0000000000000200	/* no-execute */
-#define SLB_VSID_L		0x0000000000000100	/* largepage (4M) */
-#define SLB_VSID_C		0x0000000000000080	/* class */
-
-#define SLB_VSID_KERNEL		(SLB_VSID_KP|SLB_VSID_C)
-#define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS)
+/*
+ * WARNING - If you change these you must make sure the asm
+ * implementations in slb_allocate (slb_low.S), do_stab_bolted
+ * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
+ *
+ * You'll also need to change the precomputed VSID values in head.S
+ * which are used by the iSeries firmware.
+ */
 
 #define VSID_MULTIPLIER	ASM_CONST(200730139)	/* 28-bit prime */
 #define VSID_BITS	36
@@ -239,4 +294,50 @@
 	srdi	rx,rx,VSID_BITS;	/* extract 2^36 bit */		\
 	add	rt,rt,rx
 
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_context_id_t;
+
+typedef struct {
+	mm_context_id_t id;
+#ifdef CONFIG_HUGETLB_PAGE
+	pgd_t *huge_pgdir;
+	u16 htlb_segs; /* bitmask */
+#endif
+} mm_context_t;
+
+
+static inline unsigned long vsid_scramble(unsigned long protovsid)
+{
+#if 0
+	/* The code below is equivalent to this function for arguments
+	 * < 2^VSID_BITS, which is all this should ever be called
+	 * with.  However gcc is not clever enough to compute the
+	 * modulus (2^n-1) without a second multiply. */
+	return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
+#else /* 1 */
+	unsigned long x;
+
+	x = protovsid * VSID_MULTIPLIER;
+	x = (x >> VSID_BITS) + (x & VSID_MODULUS);
+	return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
+#endif /* 1 */
+}
+
+/* This is only valid for addresses >= KERNELBASE */
+static inline unsigned long get_kernel_vsid(unsigned long ea)
+{
+	return vsid_scramble(ea >> SID_SHIFT);
+}
+
+/* This is only valid for user addresses (which are below 2^41) */
+static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
+{
+	return vsid_scramble((context << USER_ESID_BITS)
+			     | (ea >> SID_SHIFT));
+}
+
+#endif /* __ASSEMBLY */
+
 #endif /* _PPC64_MMU_H_ */
diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
index c2e8e04..77a7434 100644
--- a/include/asm-ppc64/mmu_context.h
+++ b/include/asm-ppc64/mmu_context.h
@@ -84,86 +84,4 @@
 	local_irq_restore(flags);
 }
 
-/* VSID allocation
- * ===============
- *
- * We first generate a 36-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID, for user addresses it is:
- *	(context << 15) | (esid & 0x7fff)
- *
- * The two forms are distinguishable because the top bit is 0 for user
- * addresses, whereas the top two bits are 1 for kernel addresses.
- * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
- * now.
- *
- * The proto-VSIDs are then scrambled into real VSIDs with the
- * multiplicative hash:
- *
- *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
- *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
- *
- * This scramble is only well defined for proto-VSIDs below
- * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
- * reserved.  VSID_MULTIPLIER is prime, so in particular it is
- * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
- * Because the modulus is 2^n-1 we can compute it efficiently without
- * a divide or extra multiply (see below).
- *
- * This scheme has several advantages over older methods:
- *
- * 	- We have VSIDs allocated for every kernel address
- * (i.e. everything above 0xC000000000000000), except the very top
- * segment, which simplifies several things.
- *
- * 	- We allow for 15 significant bits of ESID and 20 bits of
- * context for user addresses.  i.e. 8T (43 bits) of address space for
- * up to 1M contexts (although the page table structure and context
- * allocation will need changes to take advantage of this).
- *
- * 	- The scramble function gives robust scattering in the hash
- * table (at least based on some initial results).  The previous
- * method was more susceptible to pathological cases giving excessive
- * hash collisions.
- */
-
-/*
- * WARNING - If you change these you must make sure the asm
- * implementations in slb_allocate(), do_stab_bolted and mmu.h
- * (ASM_VSID_SCRAMBLE macro) are changed accordingly.
- *
- * You'll also need to change the precomputed VSID values in head.S
- * which are used by the iSeries firmware.
- */
-
-static inline unsigned long vsid_scramble(unsigned long protovsid)
-{
-#if 0
-	/* The code below is equivalent to this function for arguments
-	 * < 2^VSID_BITS, which is all this should ever be called
-	 * with.  However gcc is not clever enough to compute the
-	 * modulus (2^n-1) without a second multiply. */
-	return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
-#else /* 1 */
-	unsigned long x;
-
-	x = protovsid * VSID_MULTIPLIER;
-	x = (x >> VSID_BITS) + (x & VSID_MODULUS);
-	return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
-#endif /* 1 */
-}
-
-/* This is only valid for addresses >= KERNELBASE */
-static inline unsigned long get_kernel_vsid(unsigned long ea)
-{
-	return vsid_scramble(ea >> SID_SHIFT);
-}
-
-/* This is only valid for user addresses (which are below 2^41) */
-static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
-{
-	return vsid_scramble((context << USER_ESID_BITS)
-			     | (ea >> SID_SHIFT));
-}
-
 #endif /* __PPC64_MMU_CONTEXT_H */
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index 20e0f19..bcd2178 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -23,7 +23,6 @@
 #define PAGE_SHIFT	12
 #define PAGE_SIZE	(ASM_CONST(1) << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
-#define PAGE_OFFSET_MASK (PAGE_SIZE-1)
 
 #define SID_SHIFT       28
 #define SID_MASK        0xfffffffffUL
@@ -85,9 +84,6 @@
 /* align addr on a size boundary - adjust address up if needed */
 #define _ALIGN(addr,size)     _ALIGN_UP(addr,size)
 
-/* to align the pointer to the (next) double word boundary */
-#define DOUBLEWORD_ALIGN(addr)	_ALIGN(addr,sizeof(unsigned long))
-
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)	_ALIGN(addr, PAGE_SIZE)
 
@@ -100,7 +96,6 @@
 #define REGION_SIZE   4UL
 #define REGION_SHIFT  60UL
 #define REGION_MASK   (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT)
-#define REGION_STRIDE (1UL << REGION_SHIFT)
 
 static __inline__ void clear_page(void *addr)
 {
@@ -209,13 +204,13 @@
 #define VMALLOCBASE     ASM_CONST(0xD000000000000000)
 #define IOREGIONBASE    ASM_CONST(0xE000000000000000)
 
-#define IO_REGION_ID       (IOREGIONBASE>>REGION_SHIFT)
-#define VMALLOC_REGION_ID  (VMALLOCBASE>>REGION_SHIFT)
-#define KERNEL_REGION_ID   (KERNELBASE>>REGION_SHIFT)
+#define IO_REGION_ID       (IOREGIONBASE >> REGION_SHIFT)
+#define VMALLOC_REGION_ID  (VMALLOCBASE >> REGION_SHIFT)
+#define KERNEL_REGION_ID   (KERNELBASE >> REGION_SHIFT)
 #define USER_REGION_ID     (0UL)
-#define REGION_ID(X)	   (((unsigned long)(X))>>REGION_SHIFT)
+#define REGION_ID(ea)	   (((unsigned long)(ea)) >> REGION_SHIFT)
 
-#define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE)
+#define __bpn_to_ba(x) ((((unsigned long)(x)) << PAGE_SHIFT) + KERNELBASE)
 #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
 
 #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
@@ -252,10 +247,19 @@
 
 /*
  * This is the default if a program doesn't have a PT_GNU_STACK
- * program header entry.
+ * program header entry. The PPC64 ELF ABI has a non executable stack
+ * stack by default, so in the absense of a PT_GNU_STACK program header
+ * we turn execute permission off.
  */
-#define VM_STACK_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
-				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_STACK_DEFAULT_FLAGS32	(VM_READ | VM_WRITE | VM_EXEC | \
+					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define VM_STACK_DEFAULT_FLAGS64	(VM_READ | VM_WRITE | \
+					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define VM_STACK_DEFAULT_FLAGS \
+	(test_thread_flag(TIF_32BIT) ? \
+	 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
 
 #endif /* __KERNEL__ */
 #endif /* _PPC64_PAGE_H */
diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
index 16232d7..4fc4b73 100644
--- a/include/asm-ppc64/pgalloc.h
+++ b/include/asm-ppc64/pgalloc.h
@@ -27,7 +27,7 @@
 	kmem_cache_free(zero_cache, pgd);
 }
 
-#define pgd_populate(MM, PGD, PMD)	pgd_set(PGD, PMD)
+#define pud_populate(MM, PUD, PMD)	pud_set(PUD, PMD)
 
 static inline pmd_t *
 pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index a261205..264c4f7 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -1,8 +1,6 @@
 #ifndef _PPC64_PGTABLE_H
 #define _PPC64_PGTABLE_H
 
-#include <asm-generic/4level-fixup.h>
-
 /*
  * This file contains the functions and defines necessary to modify and use
  * the ppc64 hashed page table.
@@ -17,15 +15,7 @@
 #include <asm/tlbflush.h>
 #endif /* __ASSEMBLY__ */
 
-/* PMD_SHIFT determines what a second-level page table entry can map */
-#define PMD_SHIFT	(PAGE_SHIFT + PAGE_SHIFT - 3)
-#define PMD_SIZE	(1UL << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT - 3) + (PAGE_SHIFT - 2))
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+#include <asm-generic/pgtable-nopud.h>
 
 /*
  * Entries per page directory level.  The PTE level must use a 64b record
@@ -40,40 +30,30 @@
 #define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
 #define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
 
-#define USER_PTRS_PER_PGD	(1024)
-#define FIRST_USER_ADDRESS	0
+/* PMD_SHIFT determines what a second-level page table entry can map */
+#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
 
-#define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
-                    PGD_INDEX_SIZE + PAGE_SHIFT) 
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+#define FIRST_USER_ADDRESS	0
 
 /*
  * Size of EA range mapped by our pagetables.
  */
-#define PGTABLE_EA_BITS	41
-#define PGTABLE_EA_MASK	((1UL<<PGTABLE_EA_BITS)-1)
+#define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
+                    PGD_INDEX_SIZE + PAGE_SHIFT)
+#define EADDR_MASK ((1UL << EADDR_SIZE) - 1)
 
 /*
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_END   (VMALLOC_START + PGTABLE_EA_MASK)
-
-/*
- * Define the address range of the imalloc VM area.
- * (used for ioremap)
- */
-#define IMALLOC_START     (ioremap_bot)
-#define IMALLOC_VMADDR(x) ((unsigned long)(x))
-#define PHBS_IO_BASE  	  (0xE000000000000000ul)	/* Reserve 2 gigs for PHBs */
-#define IMALLOC_BASE      (0xE000000080000000ul)  
-#define IMALLOC_END       (IMALLOC_BASE + PGTABLE_EA_MASK)
-
-/*
- * Define the user address range
- */
-#define USER_START (0UL)
-#define USER_END   (USER_START + PGTABLE_EA_MASK)
-
+#define VMALLOC_END   (VMALLOC_START + EADDR_MASK)
 
 /*
  * Bits in a linux-style PTE.  These match the bits in the
@@ -168,10 +148,6 @@
 /* shift to put page number into pte */
 #define PTE_SHIFT (17)
 
-/* We allow 2^41 bytes of real memory, so we need 29 bits in the PMD
- * to give the PTE page number.  The bottom two bits are for flags. */
-#define PMD_TO_PTEPAGE_SHIFT (2)
-
 #ifdef CONFIG_HUGETLB_PAGE
 
 #ifndef __ASSEMBLY__
@@ -200,13 +176,14 @@
  */
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
-#define pfn_pte(pfn,pgprot)						\
-({									\
-	pte_t pte;							\
-	pte_val(pte) = ((unsigned long)(pfn) << PTE_SHIFT) |   		\
-                        pgprot_val(pgprot);				\
-	pte;								\
-})
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
+{
+	pte_t pte;
+
+
+	pte_val(pte) = (pfn << PTE_SHIFT) | pgprot_val(pgprot);
+	return pte;
+}
 
 #define pte_modify(_pte, newprot) \
   (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
@@ -220,20 +197,20 @@
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
 
 #define pmd_set(pmdp, ptep) 	\
-	(pmd_val(*(pmdp)) = (__ba_to_bpn(ptep) << PMD_TO_PTEPAGE_SHIFT))
+	(pmd_val(*(pmdp)) = __ba_to_bpn(ptep))
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define	pmd_bad(pmd)		(pmd_val(pmd) == 0)
 #define	pmd_present(pmd)	(pmd_val(pmd) != 0)
 #define	pmd_clear(pmdp)		(pmd_val(*(pmdp)) = 0)
-#define pmd_page_kernel(pmd)	\
-	(__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT))
+#define pmd_page_kernel(pmd)	(__bpn_to_ba(pmd_val(pmd)))
 #define pmd_page(pmd)		virt_to_page(pmd_page_kernel(pmd))
-#define pgd_set(pgdp, pmdp)	(pgd_val(*(pgdp)) = (__ba_to_bpn(pmdp)))
-#define pgd_none(pgd)		(!pgd_val(pgd))
-#define pgd_bad(pgd)		((pgd_val(pgd)) == 0)
-#define pgd_present(pgd)	(pgd_val(pgd) != 0UL)
-#define pgd_clear(pgdp)		(pgd_val(*(pgdp)) = 0UL)
-#define pgd_page(pgd)		(__bpn_to_ba(pgd_val(pgd))) 
+
+#define pud_set(pudp, pmdp)	(pud_val(*(pudp)) = (__ba_to_bpn(pmdp)))
+#define pud_none(pud)		(!pud_val(pud))
+#define pud_bad(pud)		((pud_val(pud)) == 0UL)
+#define pud_present(pud)	(pud_val(pud) != 0UL)
+#define pud_clear(pudp)		(pud_val(*(pudp)) = 0UL)
+#define pud_page(pud)		(__bpn_to_ba(pud_val(pud)))
 
 /* 
  * Find an entry in a page-table-directory.  We combine the address region 
@@ -245,12 +222,13 @@
 #define pgd_offset(mm, address)	 ((mm)->pgd + pgd_index(address))
 
 /* Find an entry in the second-level page table.. */
-#define pmd_offset(dir,addr) \
-  ((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
+#define pmd_offset(pudp,addr) \
+  ((pmd_t *) pud_page(*(pudp)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
 
 /* Find an entry in the third-level page table.. */
 #define pte_offset_kernel(dir,addr) \
-  ((pte_t *) pmd_page_kernel(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+  ((pte_t *) pmd_page_kernel(*(dir)) \
+ + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 
 #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
 #define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
@@ -264,8 +242,6 @@
 /* to find an entry in the ioremap page-table-directory */
 #define pgd_offset_i(address) (ioremap_pgd + pgd_index(address))
 
-#define pages_to_mb(x)		((x) >> (20-PAGE_SHIFT))
-
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
@@ -440,7 +416,7 @@
 		pte_clear(mm, addr, ptep);
 		flush_tlb_pending();
 	}
-	*ptep = __pte(pte_val(pte)) & ~_PAGE_HPTEFLAGS;
+	*ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
 }
 
 /* Set the dirty and/or accessed bits atomically in a linux PTE, this
@@ -485,18 +461,13 @@
 
 extern unsigned long ioremap_bot, ioremap_base;
 
-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
-
-#define pte_ERROR(e) \
-	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
 	printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e))
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e))
 
-extern pgd_t swapper_pg_dir[1024];
-extern pgd_t ioremap_dir[1024];
+extern pgd_t swapper_pg_dir[];
+extern pgd_t ioremap_dir[];
 
 extern void paging_init(void);
 
@@ -538,43 +509,11 @@
  */
 #define kern_addr_valid(addr)	(1)
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
-#define GET_IOSPACE(pfn)		0
-#define GET_PFN(pfn)			(pfn)
-
 void pgtable_cache_init(void);
 
-extern void hpte_init_native(void);
-extern void hpte_init_lpar(void);
-extern void hpte_init_iSeries(void);
-
-/* imalloc region types */
-#define IM_REGION_UNUSED	0x1
-#define IM_REGION_SUBSET	0x2
-#define IM_REGION_EXISTS	0x4
-#define IM_REGION_OVERLAP	0x8
-#define IM_REGION_SUPERSET	0x10
-
-extern struct vm_struct * im_get_free_area(unsigned long size);
-extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-			int region_type);
-unsigned long im_free(void *addr);
-
-extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
-				     unsigned long va, unsigned long prpn,
-				     int secondary, unsigned long hpteflags,
-				     int bolted, int large);
-
-extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
-			       unsigned long prpn, int secondary,
-			       unsigned long hpteflags, int bolted, int large);
-
 /*
  * find_linux_pte returns the address of a linux pte for a given 
  * effective address and directory.  If not found, it returns zero.
@@ -582,19 +521,22 @@
 static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
 {
 	pgd_t *pg;
+	pud_t *pu;
 	pmd_t *pm;
 	pte_t *pt = NULL;
 	pte_t pte;
 
 	pg = pgdir + pgd_index(ea);
 	if (!pgd_none(*pg)) {
-
-		pm = pmd_offset(pg, ea);
-		if (pmd_present(*pm)) { 
-			pt = pte_offset_kernel(pm, ea);
-			pte = *pt;
-			if (!pte_present(pte))
-				pt = NULL;
+		pu = pud_offset(pg, ea);
+		if (!pud_none(*pu)) {
+			pm = pmd_offset(pu, ea);
+			if (pmd_present(*pm)) {
+				pt = pte_offset_kernel(pm, ea);
+				pte = *pt;
+				if (!pte_present(pte))
+					pt = NULL;
+			}
 		}
 	}
 
diff --git a/include/asm-ppc64/signal.h b/include/asm-ppc64/signal.h
index fe5401a..432df7dd 100644
--- a/include/asm-ppc64/signal.h
+++ b/include/asm-ppc64/signal.h
@@ -96,47 +96,20 @@
 
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
-#ifdef __KERNEL__
 
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void __sigfunction(int);
-typedef __sigfunction __user * __sighandler_t;
-
-/* Type of the restorer function */
-typedef void __sigrestorer(void);
-typedef __sigrestorer __user * __sigrestorer_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 struct old_sigaction {
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
 	unsigned long sa_flags;
-	__sigrestorer_t sa_restorer;
+	__sigrestore_t sa_restorer;
 };
 
 struct sigaction {
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
-	__sigrestorer_t sa_restorer;
+	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
 
diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h
index a9b2a11..acd1156 100644
--- a/include/asm-ppc64/spinlock.h
+++ b/include/asm-ppc64/spinlock.h
@@ -110,7 +110,7 @@
 			HMT_low();
 			if (SHARED_PROCESSOR)
 				__spin_yield(lock);
-		} while (likely(lock->lock != 0));
+		} while (unlikely(lock->lock != 0));
 		HMT_medium();
 	}
 }
@@ -128,7 +128,7 @@
 			HMT_low();
 			if (SHARED_PROCESSOR)
 				__spin_yield(lock);
-		} while (likely(lock->lock != 0));
+		} while (unlikely(lock->lock != 0));
 		HMT_medium();
 		local_irq_restore(flags_dis);
 	}
@@ -194,7 +194,7 @@
 			HMT_low();
 			if (SHARED_PROCESSOR)
 				__rw_yield(rw);
-		} while (likely(rw->lock < 0));
+		} while (unlikely(rw->lock < 0));
 		HMT_medium();
 	}
 }
@@ -251,7 +251,7 @@
 			HMT_low();
 			if (SHARED_PROCESSOR)
 				__rw_yield(rw);
-		} while (likely(rw->lock != 0));
+		} while (unlikely(rw->lock != 0));
 		HMT_medium();
 	}
 }
diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h
index 0027da4..fdec5e7 100644
--- a/include/asm-ppc64/xics.h
+++ b/include/asm-ppc64/xics.h
@@ -30,7 +30,4 @@
 
 extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
-extern unsigned int default_distrib_server;
-extern unsigned int interrupt_server_size;
-
 #endif /* _PPC64_KERNEL_XICS_H */
diff --git a/include/asm-s390/bug.h b/include/asm-s390/bug.h
index 2b8d6d4..a2e7430 100644
--- a/include/asm-s390/bug.h
+++ b/include/asm-s390/bug.h
@@ -3,12 +3,15 @@
 
 #include <linux/kernel.h>
 
+#ifdef CONFIG_BUG
 #define BUG() do { \
         printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
         __asm__ __volatile__(".long 0"); \
 } while (0)
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h
index 1bfe2bd..dae1dd4 100644
--- a/include/asm-s390/cmb.h
+++ b/include/asm-s390/cmb.h
@@ -52,7 +52,7 @@
 #define BIODASDREADALLCMB	_IOWR(DASD_IOCTL_LETTER,33,struct cmbdata)
 
 #ifdef __KERNEL__
-
+struct ccw_device;
 /**
  * enable_cmf() - switch on the channel measurement for a specific device
  *  @cdev:	The ccw device to be enabled
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
index 28ef235..6bbcdea 100644
--- a/include/asm-s390/debug.h
+++ b/include/asm-s390/debug.h
@@ -43,7 +43,7 @@
 #define DEBUG_OFF_LEVEL            -1 /* level where debug is switched off */
 #define DEBUG_FLUSH_ALL            -1 /* parameter to flush all areas */
 #define DEBUG_MAX_VIEWS            10 /* max number of views in proc fs */
-#define DEBUG_MAX_PROCF_LEN        16 /* max length for a proc file name */
+#define DEBUG_MAX_PROCF_LEN        64 /* max length for a proc file name */
 #define DEBUG_DEFAULT_LEVEL        3  /* initial debug level */
 
 #define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 614e2a9..2be287b 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -16,6 +16,8 @@
 #define PAGE_SHIFT      12
 #define PAGE_SIZE       (1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~(PAGE_SIZE-1))
+#define PAGE_DEFAULT_ACC	0
+#define PAGE_DEFAULT_KEY	(PAGE_DEFAULT_ACC << 4)
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 88c272c..fb46e90 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -245,7 +245,7 @@
 	psw_t wait_psw;
 
 	wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
-		PSW_MASK_MCHECK | PSW_MASK_WAIT;
+		PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY;
 #ifndef __s390x__
 	asm volatile (
 		"    basr %0,0\n"
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 1dc8066..4eff8f2 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -185,6 +185,7 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <asm/setup.h>
+#include <asm/page.h>
 
 typedef union
 {
@@ -235,6 +236,7 @@
 #define PSW_ADDR_INSN		0x7FFFFFFFUL
 
 #define PSW_BASE_BITS		0x00080000UL
+#define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 20)
 
 #define PSW_ASC_PRIMARY		0x00000000UL
 #define PSW_ASC_ACCREG		0x00004000UL
@@ -260,6 +262,7 @@
 
 #define PSW_BASE_BITS		0x0000000180000000UL
 #define PSW_BASE32_BITS		0x0000000080000000UL
+#define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 52)
 
 #define PSW_ASC_PRIMARY		0x0000000000000000UL
 #define PSW_ASC_ACCREG		0x0000400000000000UL
@@ -268,14 +271,15 @@
 
 #define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
 			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
-			 PSW_MASK_PSTATE)
+			 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
 
 #endif /* __s390x__ */
 
-#define PSW_KERNEL_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY)
+#define PSW_KERNEL_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
+			 PSW_DEFAULT_KEY)
 #define PSW_USER_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
 			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
-			 PSW_MASK_PSTATE)
+			 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
 
 /* This macro merges a NEW PSW mask specified by the user into
    the currently active PSW mask CURRENT, modifying only those
@@ -470,6 +474,12 @@
 extern void show_regs(struct pt_regs * regs);
 #endif
 
+static inline void
+psw_set_key(unsigned int key)
+{
+	asm volatile ( "spka 0(%0)" : : "d" (key) );
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _S390_PTRACE_H */
diff --git a/include/asm-s390/siginfo.h b/include/asm-s390/siginfo.h
index 7230353..e0ff1ab 100644
--- a/include/asm-s390/siginfo.h
+++ b/include/asm-s390/siginfo.h
@@ -13,12 +13,6 @@
 #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
 #endif
 
-#ifdef CONFIG_ARCH_S390X
-#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4)
-#else
-#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
-#endif
-
 #include <asm-generic/siginfo.h>
 
 #endif
diff --git a/include/asm-s390/signal.h b/include/asm-s390/signal.h
index f273cdc..3d6e11c 100644
--- a/include/asm-s390/signal.h
+++ b/include/asm-s390/signal.h
@@ -117,30 +117,7 @@
 #define MINSIGSTKSZ     2048
 #define SIGSTKSZ        8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE                SA_ONESHOT
-#define SA_SAMPLE_RANDOM        SA_RESTART
-#define SA_SHIRQ                0x04000000
-#endif
-
-#define SIG_BLOCK          0    /* for blocking signals */
-#define SIG_UNBLOCK        1    /* for unblocking signals */
-#define SIG_SETMASK        2    /* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR ((__sighandler_t)-1)    /* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index 7017221..70508a3 100644
--- a/include/asm-sh/bug.h
+++ b/include/asm-sh/bug.h
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_BUG
 /*
  * Tell the user there is some problem.
  */
@@ -12,6 +13,8 @@
 } while (0)
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
index 5113c7f..5ebd0f2 100644
--- a/include/asm-sh/checksum.h
+++ b/include/asm-sh/checksum.h
@@ -42,7 +42,7 @@
  *	passed in an incorrect kernel address to one of these functions. 
  *	
  *	If you use these functions directly please don't forget the 
- *	verify_area().
+ *	access_ok().
  */
 static __inline__
 unsigned int csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst,
diff --git a/include/asm-sh/floppy.h b/include/asm-sh/floppy.h
index f030ca0..38d7a29 100644
--- a/include/asm-sh/floppy.h
+++ b/include/asm-sh/floppy.h
@@ -227,7 +227,7 @@
 	return 0;
 }
 
-struct fd_routine_l {
+static struct fd_routine_l {
 	int (*_request_dma)(unsigned int dmanr, const char * device_id);
 	void (*_free_dma)(unsigned int dmanr);
 	int (*_get_dma_residue)(unsigned int dummy);
diff --git a/include/asm-sh/signal.h b/include/asm-sh/signal.h
index 0a7ff71..d6e8eb0 100644
--- a/include/asm-sh/signal.h
+++ b/include/asm-sh/signal.h
@@ -108,30 +108,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-sh64/bug.h b/include/asm-sh64/bug.h
index 3acd54d..5d659ec 100644
--- a/include/asm-sh64/bug.h
+++ b/include/asm-sh64/bug.h
@@ -17,10 +17,6 @@
 		BUG(); \
 } while(0)
 
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
 #define WARN_ON(condition) do { \
 	if (unlikely((condition)!=0)) { \
 		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
diff --git a/include/asm-sh64/checksum.h b/include/asm-sh64/checksum.h
index aa3911a..fd034e9 100644
--- a/include/asm-sh64/checksum.h
+++ b/include/asm-sh64/checksum.h
@@ -34,7 +34,7 @@
  *	passed in an incorrect kernel address to one of these functions.
  *
  *	If you use these functions directly please don't forget the
- *	verify_area().
+ *	access_ok().
  */
 
 
diff --git a/include/asm-sh64/signal.h b/include/asm-sh64/signal.h
index 77957e9..2400dc6 100644
--- a/include/asm-sh64/signal.h
+++ b/include/asm-sh64/signal.h
@@ -107,30 +107,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	THREAD_SIZE
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct old_sigaction {
diff --git a/include/asm-sparc/bug.h b/include/asm-sparc/bug.h
index 0d30a67..0415120 100644
--- a/include/asm-sparc/bug.h
+++ b/include/asm-sparc/bug.h
@@ -1,6 +1,7 @@
 #ifndef _SPARC_BUG_H
 #define _SPARC_BUG_H
 
+#ifdef CONFIG_BUG
 /* Only use the inline asm until a gcc release that can handle __builtin_trap
  * -rob 2003-06-25
  *
@@ -26,6 +27,8 @@
 #endif
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h
index 8c01c5f..ed41c8b 100644
--- a/include/asm-sparc/errno.h
+++ b/include/asm-sparc/errno.h
@@ -107,4 +107,8 @@
 #define	EKEYREVOKED	130	/* Key has been revoked */
 #define	EKEYREJECTED	131	/* Key was rejected by service */
 
+/* for robust mutexes */
+#define	EOWNERDEAD	132	/* Owner died */
+#define	ENOTRECOVERABLE	133	/* State not recoverable */
+
 #endif
diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
index 780ee7f..caf9261 100644
--- a/include/asm-sparc/floppy.h
+++ b/include/asm-sparc/floppy.h
@@ -227,7 +227,7 @@
 	doing_pdma = 0;
 	if (pdma_base) {
 		mmu_unlockarea(pdma_base, pdma_areasize);
-		pdma_base = 0;
+		pdma_base = NULL;
 	}
 }
 
diff --git a/include/asm-sparc/mxcc.h b/include/asm-sparc/mxcc.h
index efe4e84..60ef9d6 100644
--- a/include/asm-sparc/mxcc.h
+++ b/include/asm-sparc/mxcc.h
@@ -115,8 +115,8 @@
 {
 	unsigned long mxcc_control;
 
-	__asm__ __volatile__("set -1, %%g2\n\t"
-			     "set -1, %%g3\n\t"
+	__asm__ __volatile__("set 0xffffffff, %%g2\n\t"
+			     "set 0xffffffff, %%g3\n\t"
 			     "stda %%g2, [%1] %2\n\t"
 			     "lda [%3] %2, %0\n\t" :
 			     "=r" (mxcc_control) :
diff --git a/include/asm-sparc/signal.h b/include/asm-sparc/signal.h
index d8211cb..aa9960a 100644
--- a/include/asm-sparc/signal.h
+++ b/include/asm-sparc/signal.h
@@ -143,7 +143,6 @@
 #define SA_ONESHOT	_SV_RESET
 #define SA_INTERRUPT	0x10u
 #define SA_NOMASK	0x20u
-#define SA_SHIRQ	0x40u
 #define SA_NOCLDWAIT	0x100u
 #define SA_SIGINFO	0x200u
 
@@ -162,11 +161,6 @@
 
 #ifdef __KERNEL__
 /*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- *
  * DJHR
  * SA_STATIC_ALLOC is used for the SPARC system to indicate that this
  * interrupt handler's irq structure should be statically allocated
@@ -177,21 +171,10 @@
  * statically allocated data.. which is NOT GOOD.
  *
  */
-#define SA_PROBE SA_ONESHOT
-#define SA_SAMPLE_RANDOM SA_RESTART
 #define SA_STATIC_ALLOC		0x80
 #endif
 
-/* Type of a signal handler.  */
-#ifdef __KERNEL__
-typedef void (*__sighandler_t)(int, int, struct sigcontext *, char *);
-#else
-typedef void (*__sighandler_t)(int);
-#endif
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 struct __new_sigaction {
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index 3f47889..f461144 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -18,7 +18,7 @@
 
 #ifndef __ASSEMBLY__
 
-/* Sparc is not segmented, however we need to be able to fool verify_area()
+/* Sparc is not segmented, however we need to be able to fool access_ok()
  * when doing system calls from kernel mode legitimately.
  *
  * "For historical reasons, these macros are grossly misnamed." -Linus
diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
index 25c5b1d..516bb27 100644
--- a/include/asm-sparc64/bug.h
+++ b/include/asm-sparc64/bug.h
@@ -1,6 +1,7 @@
 #ifndef _SPARC64_BUG_H
 #define _SPARC64_BUG_H
 
+#ifdef CONFIG_BUG
 #include <linux/compiler.h>
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
@@ -14,6 +15,8 @@
 #endif
 
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-sparc64/errno.h b/include/asm-sparc64/errno.h
index cc98a73..ea3509e 100644
--- a/include/asm-sparc64/errno.h
+++ b/include/asm-sparc64/errno.h
@@ -107,4 +107,8 @@
 #define	EKEYREVOKED	130	/* Key has been revoked */
 #define	EKEYREJECTED	131	/* Key was rejected by service */
 
+/* for robust mutexes */
+#define	EOWNERDEAD	132	/* Owner died */
+#define	ENOTRECOVERABLE	133	/* State not recoverable */
+
 #endif /* !(_SPARC64_ERRNO_H) */
diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
index ccf2f5f..09b5aba 100644
--- a/include/asm-sparc64/mostek.h
+++ b/include/asm-sparc64/mostek.h
@@ -38,7 +38,7 @@
  *
  * We now deal with physical addresses for I/O to the chip. -DaveM
  */
-static __inline__ u8 mostek_read(unsigned long addr)
+static __inline__ u8 mostek_read(void __iomem *addr)
 {
 	u8 ret;
 
@@ -48,7 +48,7 @@
 	return ret;
 }
 
-static __inline__ void mostek_write(unsigned long addr, u8 val)
+static __inline__ void mostek_write(void __iomem *addr, u8 val)
 {
 	__asm__ __volatile__("stba	%0, [%1] %2"
 			     : /* no outputs */
@@ -67,7 +67,7 @@
 #define MOSTEK_YEAR		0x07ffUL
 
 extern spinlock_t mostek_lock;
-extern unsigned long mstk48t02_regs;
+extern void __iomem *mstk48t02_regs;
 
 /* Control register values. */
 #define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index ab88349..b7e6355 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -13,6 +13,12 @@
 
 #define PARPORT_PC_MAX_PORTS	PARPORT_MAX
 
+/*
+ * While sparc64 doesn't have an ISA DMA API, we provide something that looks
+ * close enough to make parport_pc happy
+ */
+#define HAS_DMA
+
 static struct sparc_ebus_info {
 	struct ebus_dma_info info;
 	unsigned int addr;
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
index 2c28e1f..b9b1914 100644
--- a/include/asm-sparc64/pgalloc.h
+++ b/include/asm-sparc64/pgalloc.h
@@ -122,17 +122,12 @@
 #define pmd_populate(MM,PMD,PTE_PAGE)		\
 	pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
 
-extern pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
-	return __pte_alloc_one_kernel(mm, address);
-}
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
 
 static inline struct page *
 pte_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	pte_t *pte = __pte_alloc_one_kernel(mm, addr);
+	pte_t *pte = pte_alloc_one_kernel(mm, addr);
 
 	if (pte)
 		return virt_to_page(pte);
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index af9bf17..ae2cd5b 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -416,6 +416,11 @@
 			       unsigned long pfn,
 			       unsigned long size, pgprot_t prot);
 
+/* Clear virtual and physical cachability, set side-effect bit.  */
+#define pgprot_noncached(prot) \
+	(__pgprot((pgprot_val(prot) & ~(_PAGE_CP | _PAGE_CV)) | \
+	 _PAGE_E))
+
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
index 7160449..df17e47 100644
--- a/include/asm-sparc64/siginfo.h
+++ b/include/asm-sparc64/siginfo.h
@@ -3,8 +3,6 @@
 
 #define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
 
-#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 4)
-
 #define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
 #define __ARCH_SI_TRAPNO
 #define __ARCH_SI_BAND_T int
diff --git a/include/asm-sparc64/signal.h b/include/asm-sparc64/signal.h
index 6428e36..becdf1b 100644
--- a/include/asm-sparc64/signal.h
+++ b/include/asm-sparc64/signal.h
@@ -145,7 +145,6 @@
 #define SA_ONESHOT	_SV_RESET
 #define SA_INTERRUPT	0x10u
 #define SA_NOMASK	0x20u
-#define SA_SHIRQ	0x40u
 #define SA_NOCLDWAIT    0x100u
 #define SA_SIGINFO      0x200u
 
@@ -165,11 +164,6 @@
 
 #ifdef __KERNEL__
 /*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- *
  * DJHR
  * SA_STATIC_ALLOC is used for the SPARC system to indicate that this
  * interrupt handler's irq structure should be statically allocated
@@ -180,26 +174,10 @@
  * statically allocated data.. which is NOT GOOD.
  *
  */
-#define SA_PROBE SA_ONESHOT
-#define SA_SAMPLE_RANDOM SA_RESTART
 #define SA_STATIC_ALLOC		0x80
 #endif
 
-/* Type of a signal handler.  */
-#ifdef __KERNEL__
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-#else
-typedef void (*__sighandler_t)(int);
-typedef void (*__sigrestore_t)(void);
-#endif
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal.h>
 
 struct __new_sigaction {
 	__sighandler_t		sa_handler;
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index d1f91a4..db7581b 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -44,7 +44,7 @@
 
 #define spin_unlock_wait(lp)	\
 do {	membar("#LoadLoad");	\
-} while(lp->lock)
+} while((lp)->lock)
 
 static inline void _raw_spin_lock(spinlock_t *lock)
 {
@@ -149,7 +149,7 @@
 	unsigned int break_lock;
 #endif
 } rwlock_t;
-#define RW_LOCK_UNLOCKED	{0,}
+#define RW_LOCK_UNLOCKED	(rwlock_t) {0,}
 #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
 
 static void inline __read_lock(rwlock_t *lock)
diff --git a/include/asm-um/arch-signal-i386.h b/include/asm-um/arch-signal-i386.h
index 99a9de4..e69de29 100644
--- a/include/asm-um/arch-signal-i386.h
+++ b/include/asm-um/arch-signal-i386.h
@@ -1,24 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCH_SIGNAL_I386_H
-#define __UM_ARCH_SIGNAL_I386_H
-
-struct arch_signal_context {
-	unsigned long extrasigs[_NSIG_WORDS];
-};
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h
index 6f78de5..49e89b8 100644
--- a/include/asm-um/archparam-i386.h
+++ b/include/asm-um/archparam-i386.h
@@ -6,143 +6,6 @@
 #ifndef __UM_ARCHPARAM_I386_H
 #define __UM_ARCHPARAM_I386_H
 
-/********* Bits for asm-um/elf.h ************/
-
-#include <asm/user.h>
-
-extern char * elf_aux_platform;
-#define ELF_PLATFORM (elf_aux_platform)
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-typedef struct user_i387_struct elf_fpregset_t;
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_386
-
-#define ELF_PLAT_INIT(regs, load_addr) do { \
-	PT_REGS_EBX(regs) = 0; \
-	PT_REGS_ECX(regs) = 0; \
-	PT_REGS_EDX(regs) = 0; \
-	PT_REGS_ESI(regs) = 0; \
-	PT_REGS_EDI(regs) = 0; \
-	PT_REGS_EBP(regs) = 0; \
-	PT_REGS_EAX(regs) = 0; \
-} while(0)
-
-/* Shamelessly stolen from include/asm-i386/elf.h */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
-	pr_reg[0] = PT_REGS_EBX(regs);		\
-	pr_reg[1] = PT_REGS_ECX(regs);		\
-	pr_reg[2] = PT_REGS_EDX(regs);		\
-	pr_reg[3] = PT_REGS_ESI(regs);		\
-	pr_reg[4] = PT_REGS_EDI(regs);		\
-	pr_reg[5] = PT_REGS_EBP(regs);		\
-	pr_reg[6] = PT_REGS_EAX(regs);		\
-	pr_reg[7] = PT_REGS_DS(regs);		\
-	pr_reg[8] = PT_REGS_ES(regs);		\
-	/* fake once used fs and gs selectors? */	\
-	pr_reg[9] = PT_REGS_DS(regs);		\
-	pr_reg[10] = PT_REGS_DS(regs);		\
-	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
-	pr_reg[12] = PT_REGS_IP(regs);		\
-	pr_reg[13] = PT_REGS_CS(regs);		\
-	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
-	pr_reg[15] = PT_REGS_SP(regs);		\
-	pr_reg[16] = PT_REGS_SS(regs);		\
-} while(0);
-
-
-extern unsigned long vsyscall_ehdr;
-extern unsigned long vsyscall_end;
-extern unsigned long __kernel_vsyscall;
-
-#define VSYSCALL_BASE vsyscall_ehdr
-#define VSYSCALL_END vsyscall_end
-
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START      VSYSCALL_BASE
-#define FIXADDR_USER_END        VSYSCALL_END
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO		32
-#define AT_SYSINFO_EHDR		33
-
-#define ARCH_DLINFO						\
-do {								\
-	if ( vsyscall_ehdr ) {					\
-		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
-	}							\
-} while (0)
-
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents.  Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS						      \
-	(vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
-
-#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
-if ( vsyscall_ehdr ) {							      \
-	const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
-	const struct elf_phdr *const phdrp =				      \
-		(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
-	int i;								      \
-	Elf32_Off ofs = 0;						      \
-	for (i = 0; i < ehdrp->e_phnum; ++i) {				      \
-		struct elf_phdr phdr = phdrp[i];			      \
-		if (phdr.p_type == PT_LOAD) {				      \
-			ofs = phdr.p_offset = offset;			      \
-			offset += phdr.p_filesz;			      \
-		}							      \
-		else							      \
-			phdr.p_offset += ofs;				      \
-		phdr.p_paddr = 0; /* match other core phdrs */		      \
-		DUMP_WRITE(&phdr, sizeof(phdr));			      \
-	}								      \
-}
-#define ELF_CORE_WRITE_EXTRA_DATA					      \
-if ( vsyscall_ehdr ) {							      \
-	const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
-	const struct elf_phdr *const phdrp =				      \
-		(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
-	int i;								      \
-	for (i = 0; i < ehdrp->e_phnum; ++i) {				      \
-		if (phdrp[i].p_type == PT_LOAD)				      \
-			DUMP_WRITE((void *) phdrp[i].p_vaddr,		      \
-				   phdrp[i].p_filesz);			      \
-	}								      \
-}
-
-#define R_386_NONE	0
-#define R_386_32	1
-#define R_386_PC32	2
-#define R_386_GOT32	3
-#define R_386_PLT32	4
-#define R_386_COPY	5
-#define R_386_GLOB_DAT	6
-#define R_386_JMP_SLOT	7
-#define R_386_RELATIVE	8
-#define R_386_GOTOFF	9
-#define R_386_GOTPC	10
-#define R_386_NUM	11
-
 /********* Nothing for asm-um/hardirq.h **********/
 
 /********* Nothing for asm-um/hw_irq.h **********/
diff --git a/include/asm-um/archparam-ppc.h b/include/asm-um/archparam-ppc.h
index 0ebced9..172cd6f 100644
--- a/include/asm-um/archparam-ppc.h
+++ b/include/asm-um/archparam-ppc.h
@@ -1,26 +1,6 @@
 #ifndef __UM_ARCHPARAM_PPC_H
 #define __UM_ARCHPARAM_PPC_H
 
-/********* Bits for asm-um/elf.h ************/
-
-#define ELF_PLATFORM (0)
-
-#define ELF_ET_DYN_BASE (0x08000000)
-
-/* the following stolen from asm-ppc/elf.h */
-#define ELF_NGREG	48	/* includes nip, msr, lr, etc. */
-#define ELF_NFPREG	33	/* includes fpscr */
-/* General registers */
-typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-/* Floating point registers */
-typedef double elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-
-#define ELF_DATA        ELFDATA2MSB
-#define ELF_ARCH	EM_PPC
-
 /********* Bits for asm-um/hw_irq.h **********/
 
 struct hw_interrupt_type;
diff --git a/include/asm-um/archparam-x86_64.h b/include/asm-um/archparam-x86_64.h
index 96321c4..270ed95 100644
--- a/include/asm-um/archparam-x86_64.h
+++ b/include/asm-um/archparam-x86_64.h
@@ -7,42 +7,6 @@
 #ifndef __UM_ARCHPARAM_X86_64_H
 #define __UM_ARCHPARAM_X86_64_H
 
-#include <asm/user.h>
-
-#define ELF_PLATFORM "x86_64"
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-typedef unsigned long elf_greg_t;
-typedef struct { } elf_fpregset_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_X86_64
-
-#define ELF_PLAT_INIT(regs, load_addr)    do { \
-	PT_REGS_RBX(regs) = 0; \
-	PT_REGS_RCX(regs) = 0; \
-	PT_REGS_RDX(regs) = 0; \
-	PT_REGS_RSI(regs) = 0; \
-	PT_REGS_RDI(regs) = 0; \
-	PT_REGS_RBP(regs) = 0; \
-	PT_REGS_RAX(regs) = 0; \
-	PT_REGS_R8(regs) = 0; \
-	PT_REGS_R9(regs) = 0; \
-	PT_REGS_R10(regs) = 0; \
-	PT_REGS_R11(regs) = 0; \
-	PT_REGS_R12(regs) = 0; \
-	PT_REGS_R13(regs) = 0; \
-	PT_REGS_R14(regs) = 0; \
-	PT_REGS_R15(regs) = 0; \
-} while (0)
-
-#ifdef TIF_IA32 /* XXX */
-        clear_thread_flag(TIF_IA32);
-#endif
 
 /* No user-accessible fixmap addresses, i.e. vsyscall */
 #define FIXADDR_USER_START	0
diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S
index a3d6aab..1010153 100644
--- a/include/asm-um/common.lds.S
+++ b/include/asm-um/common.lds.S
@@ -8,11 +8,6 @@
   _sdata = .;
   PROVIDE (sdata = .);
 
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
   RODATA
 
   .unprotected : { *(.unprotected) }
@@ -20,6 +15,10 @@
   PROVIDE (_unprotected_end = .);
 
   . = ALIGN(4096);
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
   __uml_setup_start = .;
   .uml.setup.init : { *(.uml.setup.init) }
   __uml_setup_end = .;
diff --git a/include/asm-um/delay.h b/include/asm-um/delay.h
index 4069557..0985bda 100644
--- a/include/asm-um/delay.h
+++ b/include/asm-um/delay.h
@@ -4,4 +4,6 @@
 #include "asm/arch/delay.h"
 #include "asm/archparam.h"
 
+#define MILLION 1000000
+
 #endif
diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h
new file mode 100644
index 0000000..b72e235
--- /dev/null
+++ b/include/asm-um/elf-i386.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_I386_H
+#define __UM_ELF_I386_H
+
+#include "user.h"
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_386
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+	PT_REGS_EBX(regs) = 0; \
+	PT_REGS_ECX(regs) = 0; \
+	PT_REGS_EDX(regs) = 0; \
+	PT_REGS_ESI(regs) = 0; \
+	PT_REGS_EDI(regs) = 0; \
+	PT_REGS_EBP(regs) = 0; \
+	PT_REGS_EAX(regs) = 0; \
+} while(0)
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+/* Shamelessly stolen from include/asm-i386/elf.h */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
+	pr_reg[0] = PT_REGS_EBX(regs);		\
+	pr_reg[1] = PT_REGS_ECX(regs);		\
+	pr_reg[2] = PT_REGS_EDX(regs);		\
+	pr_reg[3] = PT_REGS_ESI(regs);		\
+	pr_reg[4] = PT_REGS_EDI(regs);		\
+	pr_reg[5] = PT_REGS_EBP(regs);		\
+	pr_reg[6] = PT_REGS_EAX(regs);		\
+	pr_reg[7] = PT_REGS_DS(regs);		\
+	pr_reg[8] = PT_REGS_ES(regs);		\
+	/* fake once used fs and gs selectors? */	\
+	pr_reg[9] = PT_REGS_DS(regs);		\
+	pr_reg[10] = PT_REGS_DS(regs);		\
+	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
+	pr_reg[12] = PT_REGS_IP(regs);		\
+	pr_reg[13] = PT_REGS_CS(regs);		\
+	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
+	pr_reg[15] = PT_REGS_SP(regs);		\
+	pr_reg[16] = PT_REGS_SS(regs);		\
+} while(0);
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+extern char * elf_aux_platform;
+#define ELF_PLATFORM (elf_aux_platform)
+
+#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+
+extern unsigned long vsyscall_ehdr;
+extern unsigned long vsyscall_end;
+extern unsigned long __kernel_vsyscall;
+
+#define VSYSCALL_BASE vsyscall_ehdr
+#define VSYSCALL_END vsyscall_end
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START      VSYSCALL_BASE
+#define FIXADDR_USER_END        VSYSCALL_END
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+	if ( vsyscall_ehdr ) {					\
+		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
+	}							\
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#define ELF_CORE_EXTRA_PHDRS						      \
+	(vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
+
+#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
+if ( vsyscall_ehdr ) {							      \
+	const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
+	const struct elf_phdr *const phdrp =				      \
+		(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
+	int i;								      \
+	Elf32_Off ofs = 0;						      \
+	for (i = 0; i < ehdrp->e_phnum; ++i) {				      \
+		struct elf_phdr phdr = phdrp[i];			      \
+		if (phdr.p_type == PT_LOAD) {				      \
+			ofs = phdr.p_offset = offset;			      \
+			offset += phdr.p_filesz;			      \
+		}							      \
+		else							      \
+			phdr.p_offset += ofs;				      \
+		phdr.p_paddr = 0; /* match other core phdrs */		      \
+		DUMP_WRITE(&phdr, sizeof(phdr));			      \
+	}								      \
+}
+#define ELF_CORE_WRITE_EXTRA_DATA					      \
+if ( vsyscall_ehdr ) {							      \
+	const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
+	const struct elf_phdr *const phdrp =				      \
+		(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
+	int i;								      \
+	for (i = 0; i < ehdrp->e_phnum; ++i) {				      \
+		if (phdrp[i].p_type == PT_LOAD)				      \
+			DUMP_WRITE((void *) phdrp[i].p_vaddr,		      \
+				   phdrp[i].p_filesz);			      \
+	}								      \
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-um/elf-ppc.h b/include/asm-um/elf-ppc.h
new file mode 100644
index 0000000..2998cf9
--- /dev/null
+++ b/include/asm-um/elf-ppc.h
@@ -0,0 +1,54 @@
+#ifndef __UM_ELF_PPC_H
+#define __UM_ELF_PPC_H
+
+#include "linux/config.h"
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#define elf_check_arch(x) (1)
+
+#ifdef CONFIG_64_BIT
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
+#define USE_ELF_CORE_DUMP
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
+#define ELF_PLATFORM (0)
+
+#define ELF_ET_DYN_BASE (0x08000000)
+
+/* the following stolen from asm-ppc/elf.h */
+#define ELF_NGREG	48	/* includes nip, msr, lr, etc. */
+#define ELF_NFPREG	33	/* includes fpscr */
+/* General registers */
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Floating point registers */
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#define ELF_DATA        ELFDATA2MSB
+#define ELF_ARCH	EM_PPC
+
+#endif
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
new file mode 100644
index 0000000..19309d0
--- /dev/null
+++ b/include/asm-um/elf-x86_64.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_X86_64_H
+#define __UM_ELF_X86_64_H
+
+#include <asm/user.h>
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct { } elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	((x)->e_machine == EM_X86_64)
+
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_X86_64
+
+#define ELF_PLAT_INIT(regs, load_addr)    do { \
+	PT_REGS_RBX(regs) = 0; \
+	PT_REGS_RCX(regs) = 0; \
+	PT_REGS_RDX(regs) = 0; \
+	PT_REGS_RSI(regs) = 0; \
+	PT_REGS_RDI(regs) = 0; \
+	PT_REGS_RBP(regs) = 0; \
+	PT_REGS_RAX(regs) = 0; \
+	PT_REGS_R8(regs) = 0; \
+	PT_REGS_R9(regs) = 0; \
+	PT_REGS_R10(regs) = 0; \
+	PT_REGS_R11(regs) = 0; \
+	PT_REGS_R12(regs) = 0; \
+	PT_REGS_R13(regs) = 0; \
+	PT_REGS_R14(regs) = 0; \
+	PT_REGS_R15(regs) = 0; \
+} while (0)
+
+#ifdef TIF_IA32 /* XXX */
+        clear_thread_flag(TIF_IA32); \
+#endif
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+#define ELF_PLATFORM "x86_64"
+
+#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h
index b3a7258..e69de29 100644
--- a/include/asm-um/elf.h
+++ b/include/asm-um/elf.h
@@ -1,37 +0,0 @@
-#ifndef __UM_ELF_H
-#define __UM_ELF_H
-
-#include "linux/config.h"
-#include "asm/archparam.h"
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define elf_check_arch(x) (1)
-
-#ifdef CONFIG_64_BIT
-#define ELF_CLASS ELFCLASS64
-#else
-#define ELF_CLASS ELFCLASS32
-#endif
-
-#define USE_ELF_CORE_DUMP
-
-#define R_386_NONE	0
-#define R_386_32	1
-#define R_386_PC32	2
-#define R_386_GOT32	3
-#define R_386_PLT32	4
-#define R_386_COPY	5
-#define R_386_GLOB_DAT	6
-#define R_386_JMP_SLOT	7
-#define R_386_RELATIVE	8
-#define R_386_GOTOFF	9
-#define R_386_GOTPC	10
-#define R_386_NUM	11
-
-#endif
diff --git a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
index 900f3fb..ae0ca39 100644
--- a/include/asm-um/fixmap.h
+++ b/include/asm-um/fixmap.h
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <asm/kmap_types.h>
 #include <asm/archparam.h>
+#include <asm/elf.h>
 
 /*
  * Here we define all the compile-time 'special' virtual
diff --git a/include/asm-um/ipc.h b/include/asm-um/ipc.h
index e2ddc47..a46e3d9 100644
--- a/include/asm-um/ipc.h
+++ b/include/asm-um/ipc.h
@@ -1,6 +1 @@
-#ifndef __UM_IPC_H
-#define __UM_IPC_H
-
-#include "asm/arch/ipc.h"
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-um/linkage.h b/include/asm-um/linkage.h
index 2701165..7dfce37 100644
--- a/include/asm-um/linkage.h
+++ b/include/asm-um/linkage.h
@@ -1,7 +1,6 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
+#ifndef __ASM_UM_LINKAGE_H
+#define __ASM_UM_LINKAGE_H
 
-#define FASTCALL(x)	x __attribute__((regparm(3)))
-#define fastcall        __attribute__((regparm(3)))
+#include "asm/arch/linkage.h"
 
 #endif
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 3620a08..504ea8e 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -27,7 +27,7 @@
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 
-#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64_BIT)
+#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64BIT)
 
 typedef struct { unsigned long pte_low, pte_high; } pte_t;
 typedef struct { unsigned long long pmd; } pmd_t;
@@ -45,6 +45,9 @@
 	({ (pte).pte_high = (phys) >> 32; \
 	   (pte).pte_low = (phys) | pgprot_val(prot); })
 
+#define pmd_val(x)	((x).pmd)
+#define __pmd(x) ((pmd_t) { (x) } )
+
 typedef unsigned long long pfn_t;
 typedef unsigned long long phys_t;
 
diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
index bdbc3f9..65e8bfc 100644
--- a/include/asm-um/pgtable-3level.h
+++ b/include/asm-um/pgtable-3level.h
@@ -145,11 +145,11 @@
  */
 #define PTE_FILE_MAX_BITS	32
 
-#ifdef CONFIG_64_BIT
+#ifdef CONFIG_64BIT
 
 #define pte_to_pgoff(p) ((p).pte >> 32)
 
-#define pgoff_to_pte(off) ((pte_t) { ((off) < 32) | _PAGE_FILE })
+#define pgoff_to_pte(off) ((pte_t) { ((off) << 32) | _PAGE_FILE })
 
 #else
 
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 71f9c0c..510e513 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -106,7 +106,7 @@
 /*
  * Define this if things work differently on an i386 and an i486:
  * it will (on an i486) warn about kernel memory accesses that are
- * done without a 'verify_area(VERIFY_WRITE,..)'
+ * done without a 'access_ok(VERIFY_WRITE,..)'
  */
 #undef TEST_VERIFY_AREA
 
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index 038ba6f..b2fc94f 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -17,12 +17,13 @@
 struct mm_struct;
 
 struct thread_struct {
+	/* This flag is set to 1 before calling do_fork (and analyzed in
+	 * copy_thread) to mark that we are begin called from userspace (fork /
+	 * vfork / clone), and reset to 0 after. It is left to 0 when called
+	 * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */
 	int forking;
 	int nsyscalls;
 	struct pt_regs regs;
-	unsigned long cr2;
-	int err;
-	unsigned long trap_no;
 	int singlestep_syscall;
 	void *fault_addr;
 	void *fault_catcher;
@@ -70,8 +71,6 @@
 	.forking		= 0, \
 	.nsyscalls		= 0, \
         .regs		   	= EMPTY_REGS, \
-	.cr2			= 0, \
-	.err			= 0, \
 	.fault_addr		= NULL, \
 	.prev_sched		= NULL, \
 	.temp_stack		= 0, \
@@ -89,7 +88,11 @@
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern void dump_thread(struct pt_regs *regs, struct user *u);
-extern void prepare_to_copy(struct task_struct *tsk);
+
+static inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
 
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
index 2deb8f1..431bad3 100644
--- a/include/asm-um/processor-i386.h
+++ b/include/asm-um/processor-i386.h
@@ -9,13 +9,18 @@
 extern int host_has_xmm;
 extern int host_has_cmov;
 
+/* include faultinfo structure */
+#include "sysdep/faultinfo.h"
+
 struct arch_thread {
 	unsigned long debugregs[8];
 	int debugregs_seq;
+	struct faultinfo faultinfo;
 };
 
 #define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
-                           .debugregs_seq	= 0 }
+                           .debugregs_seq	= 0, \
+                           .faultinfo		= { 0, 0, 0 } }
 
 #include "asm/arch/user.h"
 
diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h
index a1ae3a4..0beb9a4 100644
--- a/include/asm-um/processor-x86_64.h
+++ b/include/asm-um/processor-x86_64.h
@@ -7,9 +7,13 @@
 #ifndef __UM_PROCESSOR_X86_64_H
 #define __UM_PROCESSOR_X86_64_H
 
-#include "asm/arch/user.h"
+/* include faultinfo structure */
+#include "sysdep/faultinfo.h"
 
 struct arch_thread {
+        unsigned long debugregs[8];
+        int debugregs_seq;
+        struct faultinfo faultinfo;
 };
 
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
@@ -20,7 +24,11 @@
 
 #define cpu_relax()   rep_nop()
 
-#define INIT_ARCH_THREAD { }
+#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
+                           .debugregs_seq	= 0, \
+                           .faultinfo		= { 0, 0, 0 } }
+
+#include "asm/arch/user.h"
 
 #define current_text_addr() \
 	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index 9e47590..04222f3 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -6,6 +6,8 @@
 #ifndef __UM_PTRACE_I386_H
 #define __UM_PTRACE_I386_H
 
+#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+
 #include "sysdep/ptrace.h"
 #include "asm/ptrace-generic.h"
 
diff --git a/include/asm-um/ptrace-x86_64.h b/include/asm-um/ptrace-x86_64.h
index c34be39..be51219 100644
--- a/include/asm-um/ptrace-x86_64.h
+++ b/include/asm-um/ptrace-x86_64.h
@@ -14,6 +14,8 @@
 #include "asm/ptrace-generic.h"
 #undef signal_fault
 
+#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
+
 void signal_fault(struct pt_regs_subarch *regs, void *frame, char *where);
 
 #define FS_BASE (21 * sizeof(unsigned long))
diff --git a/include/asm-um/setup.h b/include/asm-um/setup.h
index c85252e..99f0863 100644
--- a/include/asm-um/setup.h
+++ b/include/asm-um/setup.h
@@ -2,7 +2,8 @@
 #define SETUP_H_INCLUDED
 
 /* POSIX mandated with _POSIX_ARG_MAX that we can rely on 4096 chars in the
- * command line, so this choice is ok.*/
+ * command line, so this choice is ok.
+ */
 
 #define COMMAND_LINE_SIZE 4096
 
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index bffb577..a10ea15 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -72,12 +72,14 @@
 					 */
 #define TIF_RESTART_BLOCK 	4
 #define TIF_MEMDIE	 	5
+#define TIF_SYSCALL_AUDIT	6
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
-#define _TIF_RESTART_BLOCK	(1 << TIF_RESTART_BLOCK)
+#define _TIF_MEMDIE		(1 << TIF_MEMDIE)
+#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 
 #endif
 
diff --git a/include/asm-v850/bug.h b/include/asm-v850/bug.h
index c778916..b0ed2d3 100644
--- a/include/asm-v850/bug.h
+++ b/include/asm-v850/bug.h
@@ -14,9 +14,12 @@
 #ifndef __V850_BUG_H__
 #define __V850_BUG_H__
 
+#ifdef CONFIG_BUG
 extern void __bug (void) __attribute__ ((noreturn));
 #define BUG()		__bug()
 #define HAVE_ARCH_BUG
+#endif
+
 #include <asm-generic/bug.h>
 
 #endif /* __V850_BUG_H__ */
diff --git a/include/asm-v850/signal.h b/include/asm-v850/signal.h
index 407db87..cb52caa 100644
--- a/include/asm-v850/signal.h
+++ b/include/asm-v850/signal.h
@@ -110,32 +110,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-
-#ifdef __KERNEL__
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif /* __KERNEL__ */
-
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
-
+#include <asm-generic/signal.h>
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index c025cc3..e4b1017 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -99,7 +99,6 @@
 extern void enable_APIC_timer(void);
 extern void clustered_apic_check(void);
 
-extern int check_nmi_watchdog(void);
 extern void nmi_watchdog_default(void);
 extern int setup_nmi_watchdog(char *);
 
diff --git a/include/asm-x86_64/bootsetup.h b/include/asm-x86_64/bootsetup.h
index b570a48..b829f7b 100644
--- a/include/asm-x86_64/bootsetup.h
+++ b/include/asm-x86_64/bootsetup.h
@@ -2,7 +2,8 @@
 #ifndef _X86_64_BOOTSETUP_H
 #define _X86_64_BOOTSETUP_H 1
 
-extern char x86_boot_params[2048];
+#define BOOT_PARAM_SIZE		4096
+extern char x86_boot_params[BOOT_PARAM_SIZE];
 
 /*
  * This is set up by the setup-routine at boot-time
diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
index 19aed6e..bdbf66e 100644
--- a/include/asm-x86_64/bug.h
+++ b/include/asm-x86_64/bug.h
@@ -15,11 +15,13 @@
 	unsigned short line;
 } __attribute__((packed));
 
+#ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
 #define BUG() \
 	asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
 		     "i"(__LINE__), "i" (__stringify(__FILE__)))
 void out_of_line_bug(void);
-#include <asm-generic/bug.h>
+#endif
 
+#include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index e68ad97..aea308c 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -7,7 +7,7 @@
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS	6
+#define NCAPINTS	7	/* N 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -74,9 +74,15 @@
 #define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
 #define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
 
-/* More extended AMD flags: CPUID level 0x80000001, ecx, word 5 */
-#define X86_FEATURE_LAHF_LM	(5*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY	(5*32+ 1) /* If yes HyperThreading not valid */
+/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
+#define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
+#define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* on-CPU RNG enabled */
+#define X86_FEATURE_XCRYPT	(5*32+ 6) /* on-CPU crypto (xcrypt insn) */
+#define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
+
+/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
+#define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
 
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 08f83a4..8e94edf 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -14,7 +14,7 @@
 #include <linux/mmzone.h>
 
 #define E820MAP	0x2d0		/* our map */
-#define E820MAX	32		/* number of entries in E820MAP */
+#define E820MAX	128		/* number of entries in E820MAP */
 #define E820NR	0x1e8		/* # entries in E820MAP */
 
 #define E820_RAM	1
diff --git a/include/asm-x86_64/floppy.h b/include/asm-x86_64/floppy.h
index bca9b28..af7ded6 100644
--- a/include/asm-x86_64/floppy.h
+++ b/include/asm-x86_64/floppy.h
@@ -223,7 +223,7 @@
 	return 0;
 }
 
-struct fd_routine_l {
+static struct fd_routine_l {
 	int (*_request_dma)(unsigned int dmanr, const char * device_id);
 	void (*_free_dma)(unsigned int dmanr);
 	int (*_get_dma_residue)(unsigned int dummy);
diff --git a/include/asm-x86_64/siginfo.h b/include/asm-x86_64/siginfo.h
index 7bc1598..d09a1e6 100644
--- a/include/asm-x86_64/siginfo.h
+++ b/include/asm-x86_64/siginfo.h
@@ -3,8 +3,6 @@
 
 #define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
 
-#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4)
-
 #include <asm-generic/siginfo.h>
 
 #endif
diff --git a/include/asm-x86_64/signal.h b/include/asm-x86_64/signal.h
index 643a20d..fe9b96d 100644
--- a/include/asm-x86_64/signal.h
+++ b/include/asm-x86_64/signal.h
@@ -116,35 +116,9 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-#ifdef __KERNEL__
-
-/*
- * These values of sa_flags are used only by the kernel as part of the
- * irq handling routines.
- *
- * SA_INTERRUPT is also used by the irq handling routines.
- * SA_SHIRQ is for shared interrupt support on PCI and EISA.
- */
-#define SA_PROBE		SA_ONESHOT
-#define SA_SAMPLE_RANDOM	SA_RESTART
-#define SA_SHIRQ		0x04000000
-#endif
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
+#include <asm-generic/signal.h>
 
 #ifndef __ASSEMBLY__
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-typedef void __restorefn_t(void);
-typedef __restorefn_t __user *__sigrestore_t;
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 
 struct sigaction {
 	__sighandler_t sa_handler;
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 3d65d24..3c9af6f 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -76,7 +76,7 @@
 #define __NR_shmget                             29
 __SYSCALL(__NR_shmget, sys_shmget)
 #define __NR_shmat                              30
-__SYSCALL(__NR_shmat, wrap_sys_shmat)
+__SYSCALL(__NR_shmat, sys_shmat)
 #define __NR_shmctl                             31
 __SYSCALL(__NR_shmctl, sys_shmctl)
 
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3628f7c..19f04b0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -1,4 +1,4 @@
-/* audit.h -- Auditing support -*- linux-c -*-
+/* audit.h -- Auditing support
  *
  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
  * All Rights Reserved.
@@ -24,6 +24,9 @@
 #ifndef _LINUX_AUDIT_H_
 #define _LINUX_AUDIT_H_
 
+#include <linux/sched.h>
+#include <linux/elf.h>
+
 /* Request and reply types */
 #define AUDIT_GET      1000	/* Get status */
 #define AUDIT_SET      1001	/* Set status (enable/disable/auditd) */
@@ -67,6 +70,7 @@
 #define AUDIT_FSGID	8
 #define AUDIT_LOGINUID	9
 #define AUDIT_PERS	10
+#define AUDIT_ARCH	11
 
 				/* These are ONLY useful when checking
 				 * at syscall exit time (AUDIT_AT_EXIT). */
@@ -96,6 +100,38 @@
 #define AUDIT_FAIL_PRINTK	1
 #define AUDIT_FAIL_PANIC	2
 
+/* distinguish syscall tables */
+#define __AUDIT_ARCH_64BIT 0x80000000
+#define __AUDIT_ARCH_LE	   0x40000000
+#define AUDIT_ARCH_ALPHA	(EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_ARM		(EM_ARM|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_ARMEB	(EM_ARM)
+#define AUDIT_ARCH_CRIS		(EM_CRIS|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_FRV		(EM_FRV)
+#define AUDIT_ARCH_H8300	(EM_H8_300)
+#define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_IA64		(EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_M32R		(EM_M32R)
+#define AUDIT_ARCH_M68K		(EM_68K)
+#define AUDIT_ARCH_MIPS		(EM_MIPS)
+#define AUDIT_ARCH_MIPSEL	(EM_MIPS|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_MIPS64	(EM_MIPS|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_MIPSEL64	(EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_PARISC	(EM_PARISC)
+#define AUDIT_ARCH_PARISC64	(EM_PARISC|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_PPC		(EM_PPC)
+#define AUDIT_ARCH_PPC64	(EM_PPC64|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_S390		(EM_S390)
+#define AUDIT_ARCH_S390X	(EM_S390|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_SH		(EM_SH)
+#define AUDIT_ARCH_SHEL		(EM_SH|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_SH64		(EM_SH|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_SHEL64	(EM_SH|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_SPARC	(EM_SPARC)
+#define AUDIT_ARCH_SPARC64	(EM_SPARC64|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_V850		(EM_V850|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+
 #ifndef __KERNEL__
 struct audit_message {
 	struct nlmsghdr nlh;
@@ -129,32 +165,36 @@
 struct audit_context;
 struct inode;
 
+#define AUDITSC_INVALID 0
+#define AUDITSC_SUCCESS 1
+#define AUDITSC_FAILURE 2
+#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
 				/* Public API */
 extern int  audit_alloc(struct task_struct *task);
 extern void audit_free(struct task_struct *task);
-extern void audit_syscall_entry(struct task_struct *task,
+extern void audit_syscall_entry(struct task_struct *task, int arch,
 				int major, unsigned long a0, unsigned long a1,
 				unsigned long a2, unsigned long a3);
-extern void audit_syscall_exit(struct task_struct *task, int return_code);
+extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
 extern void audit_getname(const char *name);
 extern void audit_putname(const char *name);
 extern void audit_inode(const char *name, const struct inode *inode);
 
 				/* Private API (for audit.c only) */
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
-				 void *data);
+				 void *data, uid_t loginuid);
 extern void audit_get_stamp(struct audit_context *ctx,
-			    struct timespec *t, int *serial);
-extern int  audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
+			    struct timespec *t, unsigned int *serial);
+extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
 extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
-#define audit_syscall_entry(t,a,b,c,d,e) do { ; } while (0)
-#define audit_syscall_exit(t,r) do { ; } while (0)
+#define audit_syscall_entry(t,ta,a,b,c,d,e) do { ; } while (0)
+#define audit_syscall_exit(t,f,r) do { ; } while (0)
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
 #define audit_inode(n,i) do { ; } while (0)
@@ -174,11 +214,15 @@
 					     const char *fmt, ...)
 			    __attribute__((format(printf,2,3)));
 extern void		    audit_log_end(struct audit_buffer *ab);
+extern void		    audit_log_hex(struct audit_buffer *ab,
+					  const unsigned char *buf,
+					  size_t len);
+extern void		    audit_log_untrustedstring(struct audit_buffer *ab,
+						      const char *string);
 extern void		    audit_log_d_path(struct audit_buffer *ab,
 					     const char *prefix,
 					     struct dentry *dentry,
 					     struct vfsmount *vfsmnt);
-
 				/* Private API (for auditsc.c only) */
 extern void		    audit_send_reply(int pid, int seq, int type,
 					     int done, int multi,
@@ -190,6 +234,8 @@
 #define audit_log_vformat(b,f,a) do { ; } while (0)
 #define audit_log_format(b,f,...) do { ; } while (0)
 #define audit_log_end(b) do { ; } while (0)
+#define audit_log_hex(a,b,l) do { ; } while (0)
+#define audit_log_untrustedstring(a,s) do { ; } while (0)
 #define audit_log_d_path(b,p,d,v) do { ; } while (0)
 #endif
 #endif
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index d1c7b0e..a1657fb 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -23,7 +23,7 @@
 #define AUTOFS_MIN_PROTO_VERSION	3
 #define AUTOFS_MAX_PROTO_VERSION	4
 
-#define AUTOFS_PROTO_SUBVERSION         5
+#define AUTOFS_PROTO_SUBVERSION		6
 
 /* Mask for expire behaviour */
 #define AUTOFS_EXP_IMMEDIATE		1
diff --git a/include/linux/awe_voice.h b/include/linux/awe_voice.h
index da0e27d..4bf9f33 100644
--- a/include/linux/awe_voice.h
+++ b/include/linux/awe_voice.h
@@ -29,9 +29,9 @@
 #define SAMPLE_TYPE_AWE32	0x20
 #endif
 
-#ifndef _PATCHKEY
-#define _PATCHKEY(id) ((id<<8)|0xfd)
-#endif
+#define _LINUX_PATCHKEY_H_INDIRECT
+#include <linux/patchkey.h>
+#undef _LINUX_PATCHKEY_H_INDIRECT
 
 /*----------------------------------------------------------------
  * patch information record
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 54f8208..7e736e2 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -77,7 +77,6 @@
 extern int setup_arg_pages(struct linux_binprm * bprm,
 			   unsigned long stack_top,
 			   int executable_stack);
-extern int copy_strings(int argc,char __user * __user * argv,struct linux_binprm *bprm); 
 extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
 extern void compute_creds(struct linux_binprm *binprm);
 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
diff --git a/include/linux/compiler-gcc2.h b/include/linux/compiler-gcc2.h
index 5a35915..ebed1766 100644
--- a/include/linux/compiler-gcc2.h
+++ b/include/linux/compiler-gcc2.h
@@ -22,3 +22,8 @@
 # define __attribute_pure__	__attribute__((pure))
 # define __attribute_const__	__attribute__((__const__))
 #endif
+
+/* GCC 2.95.x/2.96 recognize __va_copy, but not va_copy. Actually later GCC's
+ * define both va_copy and __va_copy, but the latter may go away, so limit this
+ * to this header */
+#define va_copy			__va_copy
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 487725c..d737821 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -90,6 +90,12 @@
 # define __deprecated		/* unimplemented */
 #endif
 
+#ifdef MODULE
+#define __deprecated_for_modules __deprecated
+#else
+#define __deprecated_for_modules
+#endif
+
 #ifndef __must_check
 #define __must_check
 #endif
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 910eca3..f21af06 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -103,6 +103,7 @@
 #define CPUFREQ_PRECHANGE	(0)
 #define CPUFREQ_POSTCHANGE	(1)
 #define CPUFREQ_RESUMECHANGE	(8)
+#define CPUFREQ_SUSPENDCHANGE	(9)
 
 struct cpufreq_freqs {
 	unsigned int cpu;	/* cpu nr */
@@ -200,6 +201,7 @@
 
 	/* optional */
 	int	(*exit)		(struct cpufreq_policy *policy);
+	int	(*suspend)	(struct cpufreq_policy *policy, u32 state);
 	int	(*resume)	(struct cpufreq_policy *policy);
 	struct freq_attr	**attr;
 };
@@ -211,7 +213,8 @@
 #define CPUFREQ_CONST_LOOPS 	0x02	/* loops_per_jiffy or other kernel
 					 * "constants" aren't affected by
 					 * frequency transitions */
-
+#define CPUFREQ_PM_NO_WARN	0x04	/* don't warn on suspend/resume speed
+					 * mismatches */
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
diff --git a/include/linux/edd.h b/include/linux/edd.h
index c6e6747..162512b 100644
--- a/include/linux/edd.h
+++ b/include/linux/edd.h
@@ -32,7 +32,7 @@
 
 #define EDDNR 0x1e9		/* addr of number of edd_info structs at EDDBUF
 				   in boot_params - treat this as 1 byte  */
-#define EDDBUF	0x600		/* addr of edd_info structs in boot_params */
+#define EDDBUF	0xd00		/* addr of edd_info structs in boot_params */
 #define EDDMAXNR 6		/* number of edd_info structs starting at EDDBUF  */
 #define EDDEXTSIZE 8		/* change these if you muck with the structures */
 #define EDDPARMSIZE 74
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 396c48c..220748b 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)eth.h	1.0.4	05/13/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		Relocated to include/linux where it belongs by Alan Cox 
diff --git a/include/linux/fb.h b/include/linux/fb.h
index b45d3e2..b468bf4 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -563,6 +563,9 @@
 	int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
 			    unsigned blue, unsigned transp, struct fb_info *info);
 
+	/* set color registers in batch */
+	int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
+
 	/* blank display */
 	int (*fb_blank)(int blank, struct fb_info *info);
 
diff --git a/include/linux/fddidevice.h b/include/linux/fddidevice.h
index 2e5ee47..002f636 100644
--- a/include/linux/fddidevice.h
+++ b/include/linux/fddidevice.h
@@ -10,7 +10,7 @@
  * Author:	Lawrence V. Stefani, <stefani@lkg.dec.com>
  *
  *		fddidevice.h is based on previous trdevice.h work by
- *			Ross Biro, <bir7@leland.Stanford.Edu>
+ *			Ross Biro
  *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *			Alan Cox, <gw4pts@gw4pts.ampr.org>
  *
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5df687d..0180102 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1053,83 +1053,87 @@
 int sync_inode(struct inode *inode, struct writeback_control *wbc);
 
 /**
- * &export_operations - for nfsd to communicate with file systems
- * decode_fh:      decode a file handle fragment and return a &struct dentry
- * encode_fh:      encode a file handle fragment from a dentry
- * get_name:       find the name for a given inode in a given directory
- * get_parent:     find the parent of a given directory
- * get_dentry:     find a dentry for the inode given a file handle sub-fragment
+ * struct export_operations - for nfsd to communicate with file systems
+ * @decode_fh:      decode a file handle fragment and return a &struct dentry
+ * @encode_fh:      encode a file handle fragment from a dentry
+ * @get_name:       find the name for a given inode in a given directory
+ * @get_parent:     find the parent of a given directory
+ * @get_dentry:     find a dentry for the inode given a file handle sub-fragment
  *
  * Description:
  *    The export_operations structure provides a means for nfsd to communicate
  *    with a particular exported file system  - particularly enabling nfsd and
  *    the filesystem to co-operate when dealing with file handles.
  *
- *    export_operations contains two basic operation for dealing with file handles,
- *    decode_fh() and encode_fh(), and allows for some other operations to be defined
- *    which standard helper routines use to get specific information from the
- *    filesystem.
+ *    export_operations contains two basic operation for dealing with file
+ *    handles, decode_fh() and encode_fh(), and allows for some other
+ *    operations to be defined which standard helper routines use to get
+ *    specific information from the filesystem.
  *
  *    nfsd encodes information use to determine which filesystem a filehandle
- *    applies to in the initial part of the file handle.  The remainder, termed a
- *    file handle fragment, is controlled completely by the filesystem.
- *    The standard helper routines assume that this fragment will contain one or two
- *    sub-fragments, one which identifies the file, and one which may be used to
- *    identify the (a) directory containing the file.
+ *    applies to in the initial part of the file handle.  The remainder, termed
+ *    a file handle fragment, is controlled completely by the filesystem.  The
+ *    standard helper routines assume that this fragment will contain one or
+ *    two sub-fragments, one which identifies the file, and one which may be
+ *    used to identify the (a) directory containing the file.
  *
  *    In some situations, nfsd needs to get a dentry which is connected into a
- *    specific part of the file tree.  To allow for this, it passes the function
- *    acceptable() together with a @context which can be used to see if the dentry
- *    is acceptable.  As there can be multiple dentrys for a given file, the filesystem
- *    should check each one for acceptability before looking for the next.  As soon
- *    as an acceptable one is found, it should be returned.
+ *    specific part of the file tree.  To allow for this, it passes the
+ *    function acceptable() together with a @context which can be used to see
+ *    if the dentry is acceptable.  As there can be multiple dentrys for a
+ *    given file, the filesystem should check each one for acceptability before
+ *    looking for the next.  As soon as an acceptable one is found, it should
+ *    be returned.
  *
  * decode_fh:
- *    @decode_fh is given a &struct super_block (@sb), a file handle fragment (@fh, @fh_len)
- *    and an acceptability testing function (@acceptable, @context).  It should return
- *    a &struct dentry which refers to the same file that the file handle fragment refers
- *    to,  and which passes the acceptability test.  If it cannot, it should return
- *    a %NULL pointer if the file was found but no acceptable &dentries were available, or
- *    a %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or %ENOMEM).
+ *    @decode_fh is given a &struct super_block (@sb), a file handle fragment
+ *    (@fh, @fh_len) and an acceptability testing function (@acceptable,
+ *    @context).  It should return a &struct dentry which refers to the same
+ *    file that the file handle fragment refers to,  and which passes the
+ *    acceptability test.  If it cannot, it should return a %NULL pointer if
+ *    the file was found but no acceptable &dentries were available, or a
+ *    %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or
+ *    %ENOMEM).
  *
  * encode_fh:
- *    @encode_fh should store in the file handle fragment @fh (using at most @max_len bytes)
- *    information that can be used by @decode_fh to recover the file refered to by the
- *    &struct dentry @de.  If the @connectable flag is set, the encode_fh() should store
- *    sufficient information so that a good attempt can be made to find not only
- *    the file but also it's place in the filesystem.   This typically means storing
- *    a reference to de->d_parent in the filehandle fragment.
- *    encode_fh() should return the number of bytes stored or a negative error code
- *    such as %-ENOSPC
+ *    @encode_fh should store in the file handle fragment @fh (using at most
+ *    @max_len bytes) information that can be used by @decode_fh to recover the
+ *    file refered to by the &struct dentry @de.  If the @connectable flag is
+ *    set, the encode_fh() should store sufficient information so that a good
+ *    attempt can be made to find not only the file but also it's place in the
+ *    filesystem.   This typically means storing a reference to de->d_parent in
+ *    the filehandle fragment.  encode_fh() should return the number of bytes
+ *    stored or a negative error code such as %-ENOSPC
  *
  * get_name:
- *    @get_name should find a name for the given @child in the given @parent directory.
- *    The name should be stored in the @name (with the understanding that it is already
- *    pointing to a a %NAME_MAX+1 sized buffer.   get_name() should return %0 on success,
- *    a negative error code or error.
- *    @get_name will be called without @parent->i_sem held.
+ *    @get_name should find a name for the given @child in the given @parent
+ *    directory.  The name should be stored in the @name (with the
+ *    understanding that it is already pointing to a a %NAME_MAX+1 sized
+ *    buffer.   get_name() should return %0 on success, a negative error code
+ *    or error.  @get_name will be called without @parent->i_sem held.
  *
  * get_parent:
- *    @get_parent should find the parent directory for the given @child which is also
- *    a directory.  In the event that it cannot be found, or storage space cannot be
- *    allocated, a %ERR_PTR should be returned.
+ *    @get_parent should find the parent directory for the given @child which
+ *    is also a directory.  In the event that it cannot be found, or storage
+ *    space cannot be allocated, a %ERR_PTR should be returned.
  *
  * get_dentry:
- *    Given a &super_block (@sb) and a pointer to a file-system specific inode identifier,
- *    possibly an inode number, (@inump) get_dentry() should find the identified inode and
- *    return a dentry for that inode.
- *    Any suitable dentry can be returned including, if necessary, a new dentry created
- *    with d_alloc_root.  The caller can then find any other extant dentrys by following the
- *    d_alias links.  If a new dentry was created using d_alloc_root, DCACHE_NFSD_DISCONNECTED
- *    should be set, and the dentry should be d_rehash()ed.
+ *    Given a &super_block (@sb) and a pointer to a file-system specific inode
+ *    identifier, possibly an inode number, (@inump) get_dentry() should find
+ *    the identified inode and return a dentry for that inode.  Any suitable
+ *    dentry can be returned including, if necessary, a new dentry created with
+ *    d_alloc_root.  The caller can then find any other extant dentrys by
+ *    following the d_alias links.  If a new dentry was created using
+ *    d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry
+ *    should be d_rehash()ed.
  *
- *    If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code can be returned.
- *    The @inump will be whatever was passed to nfsd_find_fh_dentry() in either the
- *    @obj or @parent parameters.
+ *    If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code
+ *    can be returned.  The @inump will be whatever was passed to
+ *    nfsd_find_fh_dentry() in either the @obj or @parent parameters.
  *
  * Locking rules:
- *  get_parent is called with child->d_inode->i_sem down
- *  get_name is not (which is possibly inconsistent)
+ *    get_parent is called with child->d_inode->i_sem down
+ *    get_name is not (which is possibly inconsistent)
  */
 
 struct export_operations {
@@ -1337,7 +1341,7 @@
 
 extern int check_disk_change(struct block_device *);
 extern int invalidate_inodes(struct super_block *);
-extern int __invalidate_device(struct block_device *, int);
+extern int __invalidate_device(struct block_device *);
 extern int invalidate_partition(struct gendisk *, int);
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 848a1ba..af7407e 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -38,14 +38,16 @@
 #define __GFP_NO_GROW	0x2000u	/* Slab internal usage */
 #define __GFP_COMP	0x4000u	/* Add compound page metadata */
 #define __GFP_ZERO	0x8000u	/* Return zeroed page on success */
+#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
 
-#define __GFP_BITS_SHIFT 16	/* Room for 16 __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 20	/* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
 
 /* if you forget to add the bitmask here kernel will crash, period */
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
 			__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
-			__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP)
+			__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
+			__GFP_NOMEMALLOC)
 
 #define GFP_ATOMIC	(__GFP_HIGH)
 #define GFP_NOIO	(__GFP_WAIT)
diff --git a/include/linux/hippidevice.h b/include/linux/hippidevice.h
index 89b3a4a..9debe6b 100644
--- a/include/linux/hippidevice.h
+++ b/include/linux/hippidevice.h
@@ -10,7 +10,7 @@
  * Author:	Jes Sorensen, <Jes.Sorensen@cern.ch>
  *
  *		hippidevice.h is based on previous fddidevice.h work by
- *			Ross Biro, <bir7@leland.Stanford.Edu>
+ *			Ross Biro
  *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *			Alan Cox, <gw4pts@gw4pts.ampr.org>
  *			Lawrence V. Stefani, <stefani@lkg.dec.com>
diff --git a/include/linux/if.h b/include/linux/if.h
index 110282d..d73a9d6 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -8,7 +8,7 @@
  * Version:	@(#)if.h	1.0.2	04/18/93
  *
  * Authors:	Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
- *		Ross Biro, <bir7@leland.Stanford.Edu>
+ *		Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		This program is free software; you can redistribute it and/or
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index bbf49bc..0856548 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -9,7 +9,7 @@
  *
  * Authors:	Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
  *		Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source.
- *		Ross Biro, <bir7@leland.Stanford.Edu>
+ *		Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Florian La Roche,
  *		Jonathan Layes <layes@loran.com>
diff --git a/include/linux/if_ltalk.h b/include/linux/if_ltalk.h
index e75e832..7652576 100644
--- a/include/linux/if_ltalk.h
+++ b/include/linux/if_ltalk.h
@@ -6,7 +6,7 @@
 #define LTALK_ALEN		1
 
 #ifdef __KERNEL__
-extern void ltalk_setup(struct net_device *);
+extern struct net_device *alloc_ltalkdev(int sizeof_priv);
 #endif
 
 #endif
diff --git a/include/linux/input.h b/include/linux/input.h
index b70df8f..72731d7 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -328,6 +328,11 @@
 #define KEY_BRIGHTNESSUP	225
 #define KEY_MEDIA		226
 
+#define KEY_SWITCHVIDEOMODE	227
+#define KEY_KBDILLUMTOGGLE	228
+#define KEY_KBDILLUMDOWN	229
+#define KEY_KBDILLUMUP		230
+
 #define KEY_UNKNOWN		240
 
 #define BTN_MISC		0x100
diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h
index 099039d..4796787 100644
--- a/include/linux/iso_fs.h
+++ b/include/linux/iso_fs.h
@@ -1,4 +1,3 @@
-
 #ifndef _ISOFS_FS_H
 #define _ISOFS_FS_H
 
@@ -163,150 +162,4 @@
 
 #define ISOFS_SUPER_MAGIC 0x9660
 
-#ifdef __KERNEL__
-/* Number conversion inlines, named after the section in ISO 9660
-   they correspond to. */
-
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-#include <linux/iso_fs_i.h>
-#include <linux/iso_fs_sb.h>
-
-static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb)
-{
-	return sb->s_fs_info;
-}
-
-static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
-{
-	return container_of(inode, struct iso_inode_info, vfs_inode);
-}
-
-static inline int isonum_711(char *p)
-{
-	return *(u8 *)p;
-}
-static inline int isonum_712(char *p)
-{
-	return *(s8 *)p;
-}
-static inline unsigned int isonum_721(char *p)
-{
-	return le16_to_cpu(get_unaligned((__le16 *)p));
-}
-static inline unsigned int isonum_722(char *p)
-{
-	return be16_to_cpu(get_unaligned((__le16 *)p));
-}
-static inline unsigned int isonum_723(char *p)
-{
-	/* Ignore bigendian datum due to broken mastering programs */
-	return le16_to_cpu(get_unaligned((__le16 *)p));
-}
-static inline unsigned int isonum_731(char *p)
-{
-	return le32_to_cpu(get_unaligned((__le32 *)p));
-}
-static inline unsigned int isonum_732(char *p)
-{
-	return be32_to_cpu(get_unaligned((__le32 *)p));
-}
-static inline unsigned int isonum_733(char *p)
-{
-	/* Ignore bigendian datum due to broken mastering programs */
-	return le32_to_cpu(get_unaligned((__le32 *)p));
-}
-extern int iso_date(char *, int);
-
-struct inode;		/* To make gcc happy */
-
-extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
-extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
-extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *);
-
-int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
-int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
-
-extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
-extern struct buffer_head *isofs_bread(struct inode *, sector_t);
-extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
-
-extern struct inode *isofs_iget(struct super_block *sb,
-                                unsigned long block,
-                                unsigned long offset);
-
-/* Because the inode number is no longer relevant to finding the
- * underlying meta-data for an inode, we are free to choose a more
- * convenient 32-bit number as the inode number.  The inode numbering
- * scheme was recommended by Sergey Vlasov and Eric Lammerts. */
-static inline unsigned long isofs_get_ino(unsigned long block,
-					  unsigned long offset,
-					  unsigned long bufbits)
-{
-	return (block << (bufbits - 5)) | (offset >> 5);
-}
-
-/* Every directory can have many redundant directory entries scattered
- * throughout the directory tree.  First there is the directory entry
- * with the name of the directory stored in the parent directory.
- * Then, there is the "." directory entry stored in the directory
- * itself.  Finally, there are possibly many ".." directory entries
- * stored in all the subdirectories.
- *
- * In order for the NFS get_parent() method to work and for the
- * general consistency of the dcache, we need to make sure the
- * "i_iget5_block" and "i_iget5_offset" all point to exactly one of
- * the many redundant entries for each directory.  We normalize the
- * block and offset by always making them point to the "."  directory.
- *
- * Notice that we do not use the entry for the directory with the name
- * that is located in the parent directory.  Even though choosing this
- * first directory is more natural, it is much easier to find the "."
- * entry in the NFS get_parent() method because it is implicitly
- * encoded in the "extent + ext_attr_length" fields of _all_ the
- * redundant entries for the directory.  Thus, it can always be
- * reached regardless of which directory entry you have in hand.
- *
- * This works because the "." entry is simply the first directory
- * record when you start reading the file that holds all the directory
- * records, and this file starts at "extent + ext_attr_length" blocks.
- * Because the "." entry is always the first entry listed in the
- * directories file, the normalized "offset" value is always 0.
- *
- * You should pass the directory entry in "de".  On return, "block"
- * and "offset" will hold normalized values.  Only directories are
- * affected making it safe to call even for non-directory file
- * types. */
-static inline void
-isofs_normalize_block_and_offset(struct iso_directory_record* de,
-				 unsigned long *block,
-				 unsigned long *offset)
-{
-	/* Only directories are normalized. */
-	if (de->flags[0] & 2) {
-		*offset = 0;
-		*block = (unsigned long)isonum_733(de->extent)
-			+ (unsigned long)isonum_711(de->ext_attr_length);
-	}
-}
-
-extern struct inode_operations isofs_dir_inode_operations;
-extern struct file_operations isofs_dir_operations;
-extern struct address_space_operations isofs_symlink_aops;
-extern struct export_operations isofs_export_ops;
-
-/* The following macros are used to check for memory leaks. */
-#ifdef LEAK_CHECK
-#define free_s leak_check_free_s
-#define malloc leak_check_malloc
-#define sb_bread leak_check_bread
-#define brelse leak_check_brelse
-extern void * leak_check_malloc(unsigned int size);
-extern void leak_check_free_s(void * obj, int size);
-extern struct buffer_head * leak_check_bread(struct super_block *sb, int block);
-extern void leak_check_brelse(struct buffer_head * bh);
-#endif /* LEAK_CHECK */
-
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/include/linux/iso_fs_i.h b/include/linux/iso_fs_i.h
deleted file mode 100644
index 59065e9..0000000
--- a/include/linux/iso_fs_i.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _ISO_FS_I
-#define _ISO_FS_I
-
-#include <linux/fs.h>
-
-enum isofs_file_format {
-	isofs_file_normal = 0,
-	isofs_file_sparse = 1,
-	isofs_file_compressed = 2,
-};
-	
-/*
- * iso fs inode data in memory
- */
-struct iso_inode_info {
-	unsigned long i_iget5_block;
-	unsigned long i_iget5_offset;
-	unsigned int i_first_extent;
-	unsigned char i_file_format;
-	unsigned char i_format_parm[3];
-	unsigned long i_next_section_block;
-	unsigned long i_next_section_offset;
-	off_t i_section_size;
-	struct inode vfs_inode;
-};
-
-#endif
diff --git a/include/linux/iso_fs_sb.h b/include/linux/iso_fs_sb.h
deleted file mode 100644
index 043b97b..0000000
--- a/include/linux/iso_fs_sb.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _ISOFS_FS_SB
-#define _ISOFS_FS_SB
-
-/*
- * iso9660 super-block data in memory
- */
-struct isofs_sb_info {
-	unsigned long s_ninodes;
-	unsigned long s_nzones;
-	unsigned long s_firstdatazone;
-	unsigned long s_log_zone_size;
-	unsigned long s_max_size;
-	
-	unsigned char s_high_sierra; /* A simple flag */
-	unsigned char s_mapping;
-	int           s_rock_offset; /* offset of SUSP fields within SU area */
-	unsigned char s_rock;
-	unsigned char s_joliet_level;
-	unsigned char s_utf8;
-	unsigned char s_cruft; /* Broken disks with high
-				  byte of length containing
-				  junk */
-	unsigned char s_unhide;
-	unsigned char s_nosuid;
-	unsigned char s_nodev;
-	unsigned char s_nocompress;
-
-	mode_t s_mode;
-	gid_t s_gid;
-	uid_t s_uid;
-	struct nls_table *s_nls_iocharset; /* Native language support table */
-};
-
-#endif
diff --git a/include/linux/ixjuser.h b/include/linux/ixjuser.h
index 8812116..fd1756d 100644
--- a/include/linux/ixjuser.h
+++ b/include/linux/ixjuser.h
@@ -42,8 +42,6 @@
  *
  *****************************************************************************/
 
-static char ixjuser_h_rcsid[] = "$Id: ixjuser.h,v 4.1 2001/08/05 00:17:37 craigs Exp $";
-
 #include <linux/telephony.h>
 
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 7c1cba4..e25b970 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -115,10 +115,19 @@
 extern int kernel_text_address(unsigned long addr);
 extern int session_of_pgrp(int pgrp);
 
+#ifdef CONFIG_PRINTK
 asmlinkage int vprintk(const char *fmt, va_list args)
 	__attribute__ ((format (printf, 1, 0)));
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
+#else
+static inline int vprintk(const char *s, va_list args)
+	__attribute__ ((format (printf, 1, 0)));
+static inline int vprintk(const char *s, va_list args) { return 0; }
+static inline int printk(const char *s, ...)
+	__attribute__ ((format (printf, 1, 2)));
+static inline int printk(const char *s, ...) { return 0; }
+#endif
 
 unsigned long int_sqrt(unsigned long);
 
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index f20c163..99ddba5 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 struct kprobe {
 	struct hlist_node hlist;
 
+	/* list of kprobes for multi-handler support */
+	struct list_head list;
+
 	/* location of the probe point */
 	kprobe_opcode_t *addr;
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index c74a74c..17518fe 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -637,9 +637,9 @@
  * These functions are passed a count `nr_to_scan' and a gfpmask.  They should
  * scan `nr_to_scan' objects, attempting to free them.
  *
- * The callback must the number of objects which remain in the cache.
+ * The callback must return the number of objects which remain in the cache.
  *
- * The callback will be passes nr_to_scan == 0 when the VM is querying the
+ * The callback will be passed nr_to_scan == 0 when the VM is querying the
  * cache size, so a fastpath for that case is appropriate.
  */
 typedef int (*shrinker_t)(int nr_to_scan, unsigned int gfp_mask);
@@ -726,6 +726,7 @@
 extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
 	unsigned long addr, unsigned long len, pgoff_t pgoff);
 extern void exit_mmap(struct mm_struct *);
+extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index dea1b00..3ca8804 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -20,9 +20,6 @@
 		struct writeback_control *wbc, get_block_t get_block);
 int mpage_writepage(struct page *page, get_block_t *get_block,
 		struct writeback_control *wbc);
-int __mpage_writepages(struct address_space *mapping,
-		struct writeback_control *wbc, get_block_t get_block,
-		writepage_t writepage);
 
 static inline int
 generic_writepages(struct address_space *mapping, struct writeback_control *wbc)
diff --git a/include/linux/net.h b/include/linux/net.h
index 7823b34..6d997ff 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -7,7 +7,7 @@
  * Version:	@(#)net.h	1.0.3	05/25/93
  *
  * Authors:	Orest Zborowski, <obz@Kodak.COM>
- *		Ross Biro, <bir7@leland.Stanford.Edu>
+ *		Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		This program is free software; you can redistribute it and/or
@@ -64,19 +64,19 @@
 #define SOCK_PASSCRED		3
 
 #ifndef ARCH_HAS_SOCKET_TYPES
-/** sock_type - Socket types
- * 
+/**
+ * enum sock_type - Socket types
+ * @SOCK_STREAM: stream (connection) socket
+ * @SOCK_DGRAM: datagram (conn.less) socket
+ * @SOCK_RAW: raw socket
+ * @SOCK_RDM: reliably-delivered message
+ * @SOCK_SEQPACKET: sequential packet socket
+ * @SOCK_PACKET: linux specific way of getting packets at the dev level.
+ *		  For writing rarp and other similar things on the user level.
+ *
  * When adding some new socket type please
  * grep ARCH_HAS_SOCKET_TYPE include/asm-* /socket.h, at least MIPS
  * overrides this enum for binary compat reasons.
- * 
- * @SOCK_STREAM - stream (connection) socket
- * @SOCK_DGRAM - datagram (conn.less) socket
- * @SOCK_RAW - raw socket
- * @SOCK_RDM - reliably-delivered message
- * @SOCK_SEQPACKET - sequential packet socket 
- * @SOCK_PACKET - linux specific way of getting packets at the dev level.
- *		  For writing rarp and other similar things on the user level.
  */
 enum sock_type {
 	SOCK_STREAM	= 1,
@@ -93,15 +93,15 @@
 
 /**
  *  struct socket - general BSD socket
- *  @state - socket state (%SS_CONNECTED, etc)
- *  @flags - socket flags (%SOCK_ASYNC_NOSPACE, etc)
- *  @ops - protocol specific socket operations
- *  @fasync_list - Asynchronous wake up list
- *  @file - File back pointer for gc
- *  @sk - internal networking protocol agnostic socket representation
- *  @wait - wait queue for several uses
- *  @type - socket type (%SOCK_STREAM, etc)
- *  @passcred - credentials (used only in Unix Sockets (aka PF_LOCAL))
+ *  @state: socket state (%SS_CONNECTED, etc)
+ *  @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc)
+ *  @ops: protocol specific socket operations
+ *  @fasync_list: Asynchronous wake up list
+ *  @file: File back pointer for gc
+ *  @sk: internal networking protocol agnostic socket representation
+ *  @wait: wait queue for several uses
+ *  @type: socket type (%SOCK_STREAM, etc)
+ *  @passcred: credentials (used only in Unix Sockets (aka PF_LOCAL))
  */
 struct socket {
 	socket_state		state;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 8d775be..ac11d73 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)dev.h	1.0.10	08/12/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
  *		Donald J. Becker, <becker@cesdis.gsfc.nasa.gov>
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index c9bacf9..9e57500 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -62,6 +62,9 @@
 	NF_IP_PRI_FILTER = 0,
 	NF_IP_PRI_NAT_SRC = 100,
 	NF_IP_PRI_SELINUX_LAST = 225,
+	NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
+	NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
+	NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
 	NF_IP_PRI_LAST = INT_MAX,
 };
 
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index f731abd..b2738ac 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -110,6 +110,7 @@
 	__u32			dst_pid;
 	__u32			dst_groups;
 	kernel_cap_t		eff_cap;
+	__u32			loginuid;	/* Login (audit) uid */
 };
 
 #define NETLINK_CB(skb)		(*(struct netlink_skb_parms*)&((skb)->cb))
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6b74fcf..39ab8c6 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -131,6 +131,7 @@
 	unsigned long allocstall;	/* direct reclaim calls */
 
 	unsigned long pgrotated;	/* pages rotated to tail of the LRU */
+	unsigned long nr_bounce;	/* pages for bounce buffers */
 };
 
 extern void get_page_state(struct page_state *ret);
diff --git a/include/linux/patchkey.h b/include/linux/patchkey.h
new file mode 100644
index 0000000..d974a6e
--- /dev/null
+++ b/include/linux/patchkey.h
@@ -0,0 +1,45 @@
+/*
+ * <linux/patchkey.h> -- definition of _PATCHKEY macro
+ *
+ * Copyright (C) 2005 Stuart Brady
+ *
+ * This exists because awe_voice.h defined its own _PATCHKEY and it wasn't
+ * clear whether removing this would break anything in userspace.
+ *
+ * Do not include this file directly.  Please use <sys/soundcard.h> instead.
+ * For kernel code, use <linux/soundcard.h>
+ */
+
+#ifndef _LINUX_PATCHKEY_H_INDIRECT
+#error "patchkey.h included directly"
+#endif
+
+#ifndef _LINUX_PATCHKEY_H
+#define _LINUX_PATCHKEY_H
+
+/* Endian macros. */
+#ifdef __KERNEL__
+#  include <asm/byteorder.h>
+#else
+#  include <endian.h>
+#endif
+
+#if defined(__KERNEL__)
+#  if defined(__BIG_ENDIAN)
+#    define _PATCHKEY(id) (0xfd00|id)
+#  elif defined(__LITTLE_ENDIAN)
+#    define _PATCHKEY(id) ((id<<8)|0x00fd)
+#  else
+#    error "could not determine byte order"
+#  endif
+#elif defined(__BYTE_ORDER)
+#  if __BYTE_ORDER == __BIG_ENDIAN
+#    define _PATCHKEY(id) (0xfd00|id)
+#  elif __BYTE_ORDER == __LITTLE_ENDIAN
+#    define _PATCHKEY(id) ((id<<8)|0x00fd)
+#  else
+#    error "could not determine byte order"
+#  endif
+#endif
+
+#endif /* _LINUX_PATCHKEY_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 3c89148..b5238bd 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -671,6 +671,7 @@
 	int  (*suspend) (struct pci_dev *dev, pm_message_t state);	/* Device suspended */
 	int  (*resume) (struct pci_dev *dev);	                /* Device woken up */
 	int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);   /* Enable wake event */
+	void (*shutdown) (struct pci_dev *dev);
 
 	struct device_driver	driver;
 	struct pci_dynids dynids;
@@ -810,7 +811,6 @@
 int pci_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
 int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
-int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_assign_resource(struct pci_dev *dev, int i);
 
@@ -941,7 +941,6 @@
 static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
 static inline void pci_disable_device(struct pci_dev *dev) { }
 static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; }
-static inline int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; }
 static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
 static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f1f75fd..ae27792 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -854,6 +854,7 @@
 #define PCI_DEVICE_ID_MYLEX_DAC960_LA	0x0020
 #define PCI_DEVICE_ID_MYLEX_DAC960_LP	0x0050
 #define PCI_DEVICE_ID_MYLEX_DAC960_BA	0xBA56
+#define PCI_DEVICE_ID_MYLEX_DAC960_GEM	0xB166
 
 #define PCI_VENDOR_ID_PICOP		0x1066
 #define PCI_DEVICE_ID_PICOP_PT86C52X	0x0001
@@ -2062,6 +2063,7 @@
 #define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
 
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
+#define PCI_DEVICE_ID_TIGON3_5752	0x1600
 #define PCI_DEVICE_ID_TIGON3_5700	0x1644
 #define PCI_DEVICE_ID_TIGON3_5701	0x1645
 #define PCI_DEVICE_ID_TIGON3_5702	0x1646
@@ -2414,6 +2416,8 @@
 #define PCI_DEVICE_ID_INTEL_ICH7_1	0x27b9
 #define PCI_DEVICE_ID_INTEL_ICH7_2	0x27c0
 #define PCI_DEVICE_ID_INTEL_ICH7_3	0x27c1
+#define PCI_DEVICE_ID_INTEL_ICH7_30	0x27b0
+#define PCI_DEVICE_ID_INTEL_ICH7_31	0x27bd
 #define PCI_DEVICE_ID_INTEL_ICH7_5	0x27c4
 #define PCI_DEVICE_ID_INTEL_ICH7_6	0x27c5
 #define PCI_DEVICE_ID_INTEL_ICH7_7	0x27c8
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 4d74743..fd276ad 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -157,9 +157,9 @@
 /**
  * rcu_read_lock - mark the beginning of an RCU read-side critical section.
  *
- * When synchronize_kernel() is invoked on one CPU while other CPUs
+ * When synchronize_rcu() is invoked on one CPU while other CPUs
  * are within RCU read-side critical sections, then the
- * synchronize_kernel() is guaranteed to block until after all the other
+ * synchronize_rcu() is guaranteed to block until after all the other
  * CPUs exit their critical sections.  Similarly, if call_rcu() is invoked
  * on one CPU while other CPUs are within RCU read-side critical
  * sections, invocation of the corresponding RCU callback is deferred
@@ -256,6 +256,21 @@
 						(p) = (v); \
 					})
 
+/**
+ * synchronize_sched - block until all CPUs have exited any non-preemptive
+ * kernel code sequences.
+ *
+ * This means that all preempt_disable code sequences, including NMI and
+ * hardware-interrupt handlers, in progress on entry will have completed
+ * before this primitive returns.  However, this does not guarantee that
+ * softirq handlers will have completed, since in some kernels
+ *
+ * This primitive provides the guarantees made by the (deprecated)
+ * synchronize_kernel() API.  In contrast, synchronize_rcu() only
+ * guarantees that rcu_read_lock() sections will have completed.
+ */
+#define synchronize_sched() synchronize_rcu()
+
 extern void rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
@@ -265,7 +280,9 @@
 				void (*func)(struct rcu_head *head)));
 extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
 				void (*func)(struct rcu_head *head)));
-extern void synchronize_kernel(void);
+extern __deprecated_for_modules void synchronize_kernel(void);
+extern void synchronize_rcu(void);
+void synchronize_idle(void);
 
 #endif /* __KERNEL__ */
 #endif /* __LINUX_RCUPDATE_H */
diff --git a/include/linux/reboot_fixups.h b/include/linux/reboot_fixups.h
new file mode 100644
index 0000000..480ea2d
--- /dev/null
+++ b/include/linux/reboot_fixups.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_REBOOT_FIXUPS_H
+#define _LINUX_REBOOT_FIXUPS_H
+
+#ifdef CONFIG_X86_REBOOTFIXUPS
+extern void mach_reboot_fixups(void);
+#else
+#define mach_reboot_fixups() ((void)(0))
+#endif
+
+#endif /* _LINUX_REBOOT_FIXUPS_H */
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index a57e973..2aef9c3 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -5,18 +5,18 @@
 #define REISERFS_ACL_VERSION	0x0001
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
-	__u32		e_id;
+	__le16		e_tag;
+	__le16		e_perm;
+	__le32		e_id;
 } reiserfs_acl_entry;
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
+	__le16		e_tag;
+	__le16		e_perm;
 } reiserfs_acl_entry_short;
 
 typedef struct {
-	__u32		a_version;
+	__le32		a_version;
 } reiserfs_acl_header;
 
 static inline size_t reiserfs_acl_size(int count)
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index bccff8b..3214862 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -114,47 +114,47 @@
 
 
 struct journal_params {
-    __u32 jp_journal_1st_block;	      /* where does journal start from on its
+    __le32 jp_journal_1st_block;	      /* where does journal start from on its
 				       * device */
-    __u32 jp_journal_dev;	      /* journal device st_rdev */
-    __u32 jp_journal_size;	      /* size of the journal */
-    __u32 jp_journal_trans_max;	      /* max number of blocks in a transaction. */
-    __u32 jp_journal_magic; 	      /* random value made on fs creation (this
+    __le32 jp_journal_dev;	      /* journal device st_rdev */
+    __le32 jp_journal_size;	      /* size of the journal */
+    __le32 jp_journal_trans_max;	      /* max number of blocks in a transaction. */
+    __le32 jp_journal_magic; 	      /* random value made on fs creation (this
 				       * was sb_journal_block_count) */
-    __u32 jp_journal_max_batch;	      /* max number of blocks to batch into a
+    __le32 jp_journal_max_batch;	      /* max number of blocks to batch into a
 				       * trans */
-    __u32 jp_journal_max_commit_age;  /* in seconds, how old can an async
+    __le32 jp_journal_max_commit_age;  /* in seconds, how old can an async
 				       * commit be */
-    __u32 jp_journal_max_trans_age;   /* in seconds, how old can a transaction
+    __le32 jp_journal_max_trans_age;   /* in seconds, how old can a transaction
 				       * be */
 };
 
 /* this is the super from 3.5.X, where X >= 10 */
 struct reiserfs_super_block_v1
 {
-    __u32 s_block_count;	   /* blocks count         */
-    __u32 s_free_blocks;           /* free blocks count    */
-    __u32 s_root_block;            /* root block number    */
+    __le32 s_block_count;	   /* blocks count         */
+    __le32 s_free_blocks;           /* free blocks count    */
+    __le32 s_root_block;            /* root block number    */
     struct journal_params s_journal;
-    __u16 s_blocksize;             /* block size */
-    __u16 s_oid_maxsize;	   /* max size of object id array, see
+    __le16 s_blocksize;             /* block size */
+    __le16 s_oid_maxsize;	   /* max size of object id array, see
 				    * get_objectid() commentary  */
-    __u16 s_oid_cursize;	   /* current size of object id array */
-    __u16 s_umount_state;          /* this is set to 1 when filesystem was
+    __le16 s_oid_cursize;	   /* current size of object id array */
+    __le16 s_umount_state;          /* this is set to 1 when filesystem was
 				    * umounted, to 2 - when not */    
     char s_magic[10];              /* reiserfs magic string indicates that
 				    * file system is reiserfs:
 				    * "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */
-    __u16 s_fs_state;	           /* it is set to used by fsck to mark which
+    __le16 s_fs_state;	           /* it is set to used by fsck to mark which
 				    * phase of rebuilding is done */
-    __u32 s_hash_function_code;    /* indicate, what hash function is being use
+    __le32 s_hash_function_code;    /* indicate, what hash function is being use
 				    * to sort names in a directory*/
-    __u16 s_tree_height;           /* height of disk tree */
-    __u16 s_bmap_nr;               /* amount of bitmap blocks needed to address
+    __le16 s_tree_height;           /* height of disk tree */
+    __le16 s_bmap_nr;               /* amount of bitmap blocks needed to address
 				    * each block of file system */
-    __u16 s_version;               /* this field is only reliable on filesystem
+    __le16 s_version;               /* this field is only reliable on filesystem
 				    * with non-standard journal */
-    __u16 s_reserved_for_journal;  /* size in blocks of journal area on main
+    __le16 s_reserved_for_journal;  /* size in blocks of journal area on main
 				    * device, we need to keep after
 				    * making fs with non-standard journal */	
 } __attribute__ ((__packed__));
@@ -165,8 +165,8 @@
 struct reiserfs_super_block
 {
     struct reiserfs_super_block_v1 s_v1;
-    __u32 s_inode_generation;
-    __u32 s_flags;                  /* Right now used only by inode-attributes, if enabled */
+    __le32 s_inode_generation;
+    __le32 s_flags;                  /* Right now used only by inode-attributes, if enabled */
     unsigned char s_uuid[16];       /* filesystem unique identifier */
     unsigned char s_label[16];      /* filesystem volume label */
     char s_unused[88] ;             /* zero filled by mkreiserfs and
@@ -225,7 +225,7 @@
 #define SB_ONDISK_JOURNAL_DEVICE(s) \
          le32_to_cpu ((SB_ONDISK_JP(s)->jp_journal_dev))
 #define SB_ONDISK_RESERVED_FOR_JOURNAL(s) \
-         le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal))
+         le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal))
 
 #define is_block_in_log_or_reserved_area(s, block) \
          block >= SB_JOURNAL_1st_RESERVED_BLOCK(s) \
@@ -269,7 +269,7 @@
 #define QUOTA_EXCEEDED -6
 
 typedef __u32 b_blocknr_t;
-typedef __u32 unp_t;
+typedef __le32 unp_t;
 
 struct unfm_nodeinfo {
     unp_t unfm_nodenum;
@@ -376,78 +376,57 @@
 // directories use this key as well as old files
 //
 struct offset_v1 {
-    __u32 k_offset;
-    __u32 k_uniqueness;
+    __le32 k_offset;
+    __le32 k_uniqueness;
 } __attribute__ ((__packed__));
 
 struct offset_v2 {
-#ifdef __LITTLE_ENDIAN
-	    /* little endian version */
-	    __u64 k_offset:60;
-	    __u64 k_type: 4;
-#else
-	    /* big endian version */
-	    __u64 k_type: 4;
-	    __u64 k_offset:60;
-#endif
+	__le64 v;
 } __attribute__ ((__packed__));
 
-#ifndef __LITTLE_ENDIAN
-typedef union {
-    struct offset_v2 offset_v2;
-    __u64 linear;
-} __attribute__ ((__packed__)) offset_v2_esafe_overlay;
-
 static inline __u16 offset_v2_k_type( const struct offset_v2 *v2 )
 {
-    offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
-    tmp.linear = le64_to_cpu( tmp.linear );
-    return (tmp.offset_v2.k_type <= TYPE_MAXTYPE)?tmp.offset_v2.k_type:TYPE_ANY;
+	__u8 type = le64_to_cpu(v2->v) >> 60;
+	return (type <= TYPE_MAXTYPE)?type:TYPE_ANY;
 }
  
 static inline void set_offset_v2_k_type( struct offset_v2 *v2, int type )
 {
-    offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2;
-    tmp->linear = le64_to_cpu(tmp->linear);
-    tmp->offset_v2.k_type = type;
-    tmp->linear = cpu_to_le64(tmp->linear);
+	v2->v = (v2->v & cpu_to_le64(~0ULL>>4)) | cpu_to_le64((__u64)type<<60);
 }
  
 static inline loff_t offset_v2_k_offset( const struct offset_v2 *v2 )
 {
-    offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2;
-    tmp.linear = le64_to_cpu( tmp.linear );
-    return tmp.offset_v2.k_offset;
+	return le64_to_cpu(v2->v) & (~0ULL>>4);
 }
 
 static inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ){
-    offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2;
-    tmp->linear = le64_to_cpu(tmp->linear);
-    tmp->offset_v2.k_offset = offset;
-    tmp->linear = cpu_to_le64(tmp->linear);
+	offset &= (~0ULL>>4);
+	v2->v = (v2->v & cpu_to_le64(15ULL<<60)) | cpu_to_le64(offset);
 }
-#else
-# define offset_v2_k_type(v2)           ((v2)->k_type)
-# define set_offset_v2_k_type(v2,val)   (offset_v2_k_type(v2) = (val))
-# define offset_v2_k_offset(v2)         ((v2)->k_offset)
-# define set_offset_v2_k_offset(v2,val) (offset_v2_k_offset(v2) = (val))
-#endif
 
 /* Key of an item determines its location in the S+tree, and
    is composed of 4 components */
 struct reiserfs_key {
-    __u32 k_dir_id;    /* packing locality: by default parent
+    __le32 k_dir_id;    /* packing locality: by default parent
 			  directory object id */
-    __u32 k_objectid;  /* object identifier */
+    __le32 k_objectid;  /* object identifier */
     union {
 	struct offset_v1 k_offset_v1;
 	struct offset_v2 k_offset_v2;
     } __attribute__ ((__packed__)) u;
 } __attribute__ ((__packed__));
 
+struct in_core_key {
+    __u32 k_dir_id;    /* packing locality: by default parent
+			  directory object id */
+    __u32 k_objectid;  /* object identifier */
+    __u64 k_offset;
+    __u8 k_type;
+};
 
 struct cpu_key {
-    struct reiserfs_key on_disk_key;
+    struct in_core_key on_disk_key;
     int version;
     int key_length; /* 3 in all cases but direct2indirect and
 		       indirect2direct conversion */
@@ -508,15 +487,15 @@
 		   item. Note that the key, not this field, is used to
 		   determine the item type, and thus which field this
 		   union contains. */
-		__u16 ih_free_space_reserved; 
+		__le16 ih_free_space_reserved;
 		/* Iff this is a directory item, this field equals the
 		   number of directory entries in the directory item. */
-		__u16 ih_entry_count; 
+		__le16 ih_entry_count;
 	} __attribute__ ((__packed__)) u;
-	__u16 ih_item_len;           /* total size of the item body */
-	__u16 ih_item_location;      /* an offset to the item body
+	__le16 ih_item_len;           /* total size of the item body */
+	__le16 ih_item_location;      /* an offset to the item body
 				      * within the block */
-	__u16 ih_version;	     /* 0 for all old items, 2 for new
+	__le16 ih_version;	     /* 0 for all old items, 2 for new
 					ones. Highest bit is set by fsck
 					temporary, cleaned after all
 					done */
@@ -670,43 +649,29 @@
 //
 static inline loff_t cpu_key_k_offset (const struct cpu_key * key)
 {
-    return (key->version == KEY_FORMAT_3_5) ?
-        key->on_disk_key.u.k_offset_v1.k_offset :
-	key->on_disk_key.u.k_offset_v2.k_offset;
+    return key->on_disk_key.k_offset;
 }
 
 static inline loff_t cpu_key_k_type (const struct cpu_key * key)
 {
-    return (key->version == KEY_FORMAT_3_5) ?
-        uniqueness2type (key->on_disk_key.u.k_offset_v1.k_uniqueness) :
-	key->on_disk_key.u.k_offset_v2.k_type;
+    return key->on_disk_key.k_type;
 }
 
 static inline void set_cpu_key_k_offset (struct cpu_key * key, loff_t offset)
 {
-    (key->version == KEY_FORMAT_3_5) ?
-        (key->on_disk_key.u.k_offset_v1.k_offset = offset) :
-	(key->on_disk_key.u.k_offset_v2.k_offset = offset);
+	key->on_disk_key.k_offset = offset;
 }
 
-
 static inline void set_cpu_key_k_type (struct cpu_key * key, int type)
 {
-    (key->version == KEY_FORMAT_3_5) ?
-        (key->on_disk_key.u.k_offset_v1.k_uniqueness = type2uniqueness (type)):
-	(key->on_disk_key.u.k_offset_v2.k_type = type);
+	key->on_disk_key.k_type = type;
 }
 
-
 static inline void cpu_key_k_offset_dec (struct cpu_key * key)
 {
-    if (key->version == KEY_FORMAT_3_5)
-	key->on_disk_key.u.k_offset_v1.k_offset --;
-    else
-	key->on_disk_key.u.k_offset_v2.k_offset --;
+	key->on_disk_key.k_offset --;
 }
 
-
 #define is_direntry_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRENTRY)
 #define is_direct_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRECT)
 #define is_indirect_cpu_key(key) (cpu_key_k_type (key) == TYPE_INDIRECT)
@@ -752,10 +717,10 @@
 /* Header of a disk block.  More precisely, header of a formatted leaf
    or internal node, and not the header of an unformatted node. */
 struct block_head {       
-  __u16 blk_level;        /* Level of a block in the tree. */
-  __u16 blk_nr_item;      /* Number of keys/items in a block. */
-  __u16 blk_free_space;   /* Block free space in bytes. */
-  __u16 blk_reserved;
+  __le16 blk_level;        /* Level of a block in the tree. */
+  __le16 blk_nr_item;      /* Number of keys/items in a block. */
+  __le16 blk_free_space;   /* Block free space in bytes. */
+  __le16 blk_reserved;
 				/* dump this in v4/planA */
   struct reiserfs_key  blk_right_delim_key; /* kept only for compatibility */
 };
@@ -819,19 +784,19 @@
 //
 struct stat_data_v1
 {
-    __u16 sd_mode;	/* file type, permissions */
-    __u16 sd_nlink;	/* number of hard links */
-    __u16 sd_uid;		/* owner */
-    __u16 sd_gid;		/* group */
-    __u32 sd_size;	/* file size */
-    __u32 sd_atime;	/* time of last access */
-    __u32 sd_mtime;	/* time file was last modified  */
-    __u32 sd_ctime;	/* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
+    __le16 sd_mode;	/* file type, permissions */
+    __le16 sd_nlink;	/* number of hard links */
+    __le16 sd_uid;		/* owner */
+    __le16 sd_gid;		/* group */
+    __le32 sd_size;	/* file size */
+    __le32 sd_atime;	/* time of last access */
+    __le32 sd_mtime;	/* time file was last modified  */
+    __le32 sd_ctime;	/* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
     union {
-	__u32 sd_rdev;
-	__u32 sd_blocks;	/* number of blocks file uses */
+	__le32 sd_rdev;
+	__le32 sd_blocks;	/* number of blocks file uses */
     } __attribute__ ((__packed__)) u;
-    __u32 sd_first_direct_byte; /* first byte of file which is stored
+    __le32 sd_first_direct_byte; /* first byte of file which is stored
 				   in a direct item: except that if it
 				   equals 1 it is a symlink and if it
 				   equals ~(__u32)0 there is no
@@ -897,20 +862,20 @@
 /* Stat Data on disk (reiserfs version of UFS disk inode minus the
    address blocks) */
 struct stat_data {
-    __u16 sd_mode;	/* file type, permissions */
-    __u16 sd_attrs;     /* persistent inode flags */
-    __u32 sd_nlink;	/* number of hard links */
-    __u64 sd_size;	/* file size */
-    __u32 sd_uid;		/* owner */
-    __u32 sd_gid;		/* group */
-    __u32 sd_atime;	/* time of last access */
-    __u32 sd_mtime;	/* time file was last modified  */
-    __u32 sd_ctime;	/* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
-    __u32 sd_blocks;
+    __le16 sd_mode;	/* file type, permissions */
+    __le16 sd_attrs;     /* persistent inode flags */
+    __le32 sd_nlink;	/* number of hard links */
+    __le64 sd_size;	/* file size */
+    __le32 sd_uid;		/* owner */
+    __le32 sd_gid;		/* group */
+    __le32 sd_atime;	/* time of last access */
+    __le32 sd_mtime;	/* time file was last modified  */
+    __le32 sd_ctime;	/* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */
+    __le32 sd_blocks;
     union {
-	__u32 sd_rdev;
-	__u32 sd_generation;
-      //__u32 sd_first_direct_byte; 
+	__le32 sd_rdev;
+	__le32 sd_generation;
+      //__le32 sd_first_direct_byte;
       /* first byte of file which is stored in a
 				       direct item: except that if it equals 1
 				       it is a symlink and if it equals
@@ -993,12 +958,12 @@
 
 struct reiserfs_de_head
 {
-  __u32 deh_offset;		/* third component of the directory entry key */
-  __u32 deh_dir_id;		/* objectid of the parent directory of the object, that is referenced
+  __le32 deh_offset;		/* third component of the directory entry key */
+  __le32 deh_dir_id;		/* objectid of the parent directory of the object, that is referenced
 					   by directory entry */
-  __u32 deh_objectid;		/* objectid of the object, that is referenced by directory entry */
-  __u16 deh_location;		/* offset of name in the whole item */
-  __u16 deh_state;		/* whether 1) entry contains stat data (for future), and 2) whether
+  __le32 deh_objectid;		/* objectid of the object, that is referenced by directory entry */
+  __le16 deh_location;		/* offset of name in the whole item */
+  __le16 deh_state;		/* whether 1) entry contains stat data (for future), and 2) whether
 					   entry is hidden (unlinked) */
 } __attribute__ ((__packed__));
 #define DEH_SIZE                  sizeof(struct reiserfs_de_head)
@@ -1058,10 +1023,10 @@
 #define de_visible(deh)	    	    test_bit_unaligned (DEH_Visible, &((deh)->deh_state))
 #define de_hidden(deh)	    	    !test_bit_unaligned (DEH_Visible, &((deh)->deh_state))
 
-extern void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid,
-				    __u32 par_dirid, __u32 par_objid);
-extern void make_empty_dir_item (char * body, __u32 dirid, __u32 objid,
-				 __u32 par_dirid, __u32 par_objid);
+extern void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid,
+				    __le32 par_dirid, __le32 par_objid);
+extern void make_empty_dir_item (char * body, __le32 dirid, __le32 objid,
+				 __le32 par_dirid, __le32 par_objid);
 
 /* array of the entry headers */
  /* get item body */
@@ -1160,9 +1125,9 @@
 /* Disk child pointer: The pointer from an internal node of the tree
    to a node that is on disk. */
 struct disk_child {
-  __u32       dc_block_number;              /* Disk child's block number. */
-  __u16       dc_size;		            /* Disk child's used space.   */
-  __u16       dc_reserved;
+  __le32       dc_block_number;              /* Disk child's block number. */
+  __le16       dc_size;		            /* Disk child's used space.   */
+  __le16       dc_reserved;
 };
 
 #define DC_SIZE (sizeof(struct disk_child))
@@ -1476,7 +1441,7 @@
   int fs_gen;                  /* saved value of `reiserfs_generation' counter
 			          see FILESYSTEM_CHANGED() macro in reiserfs_fs.h */
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
-  struct reiserfs_key  key;	      /* key pointer, to pass to block allocator or
+  struct in_core_key  key;	      /* key pointer, to pass to block allocator or
 				 another low-level subsystem */
 #endif
 } ;
@@ -1630,10 +1595,10 @@
 
 /* first block written in a commit.  */
 struct reiserfs_journal_desc {
-  __u32 j_trans_id ;			/* id of commit */
-  __u32 j_len ;			/* length of commit. len +1 is the commit block */
-  __u32 j_mount_id ;				/* mount id of this trans*/
-  __u32 j_realblock[1] ; /* real locations for each block */
+  __le32 j_trans_id ;			/* id of commit */
+  __le32 j_len ;			/* length of commit. len +1 is the commit block */
+  __le32 j_mount_id ;				/* mount id of this trans*/
+  __le32 j_realblock[1] ; /* real locations for each block */
 } ;
 
 #define get_desc_trans_id(d)   le32_to_cpu((d)->j_trans_id)
@@ -1646,9 +1611,9 @@
 
 /* last block written in a commit */
 struct reiserfs_journal_commit {
-  __u32 j_trans_id ;			/* must match j_trans_id from the desc block */
-  __u32 j_len ;			/* ditto */
-  __u32 j_realblock[1] ; /* real locations for each block */
+  __le32 j_trans_id ;			/* must match j_trans_id from the desc block */
+  __le32 j_len ;			/* ditto */
+  __le32 j_realblock[1] ; /* real locations for each block */
 } ;
 
 #define get_commit_trans_id(c) le32_to_cpu((c)->j_trans_id)
@@ -1663,9 +1628,9 @@
 ** and this transaction does not need to be replayed.
 */
 struct reiserfs_journal_header {
-  __u32 j_last_flush_trans_id ;		/* id of last fully flushed transaction */
-  __u32 j_first_unflushed_offset ;      /* offset in the log of where to start replay after a crash */
-  __u32 j_mount_id ;
+  __le32 j_last_flush_trans_id ;		/* id of last fully flushed transaction */
+  __le32 j_first_unflushed_offset ;      /* offset in the log of where to start replay after a crash */
+  __le32 j_mount_id ;
   /* 12 */ struct journal_params jh_journal;
 } ;
 
@@ -2117,7 +2082,7 @@
  struct __reiserfs_blocknr_hint {
      struct inode * inode;		/* inode passed to allocator, if we allocate unf. nodes */
      long block;			/* file offset, in blocks */
-     struct reiserfs_key key;
+     struct in_core_key key;
      struct path * path;		/* search path, used by allocator to deternine search_start by
 					 * various ways */
      struct reiserfs_transaction_handle * th; /* transaction handle is needed to log super blocks and
@@ -2144,7 +2109,7 @@
  * to use for a new object underneat it.  The locality is returned
  * in disk byte order (le).
  */
-u32 reiserfs_choose_packing(struct inode *dir);
+__le32 reiserfs_choose_packing(struct inode *dir);
 
 int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
 void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *, b_blocknr_t, int for_unformatted);
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 1eaa48e..9244c57 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -10,8 +10,8 @@
 #define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */
 
 struct reiserfs_xattr_header {
-    __u32 h_magic;              /* magic number for identification */
-    __u32 h_hash;               /* hash of the value */
+    __le32 h_magic;              /* magic number for identification */
+    __le32 h_hash;               /* hash of the value */
 };
 
 #ifdef __KERNEL__
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 32e5276..91ac97c 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -89,10 +89,14 @@
 	RTM_GETANYCAST	= 62,
 #define RTM_GETANYCAST	RTM_GETANYCAST
 
-	RTM_MAX,
-#define RTM_MAX		RTM_MAX
+	__RTM_MAX,
+#define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
 
+#define RTM_NR_MSGTYPES	(RTM_MAX + 1 - RTM_BASE)
+#define RTM_NR_FAMILIES	(RTM_NR_MSGTYPES >> 2)
+#define RTM_FAM(cmd)	(((cmd) - RTM_BASE) >> 2)
+
 /* 
    Generic structure for encapsulation of optional route information.
    It is reminiscent of sockaddr, but with sa_family replaced
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1cced97..4dbb109 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -578,7 +578,7 @@
 	unsigned long flags;	/* per process flags, defined below */
 	unsigned long ptrace;
 
-	int lock_depth;		/* Lock depth */
+	int lock_depth;		/* BKL lock depth */
 
 	int prio, static_prio;
 	struct list_head run_list;
@@ -661,7 +661,10 @@
 	struct key *thread_keyring;	/* keyring private to this thread */
 #endif
 	int oomkilladj; /* OOM kill score adjustment (bit shift). */
-	char comm[TASK_COMM_LEN];
+	char comm[TASK_COMM_LEN]; /* executable name excluding path
+				     - access with [gs]et_task_comm (which lock
+				       it with task_lock())
+				     - initialized normally by flush_old_exec */
 /* file system info */
 	int link_count, total_link_count;
 /* ipc stuff */
@@ -845,6 +848,7 @@
 extern void set_user_nice(task_t *p, long nice);
 extern int task_prio(const task_t *p);
 extern int task_nice(const task_t *p);
+extern int can_nice(const task_t *p, const int nice);
 extern int task_curr(const task_t *p);
 extern int idle_cpu(int cpu);
 extern int sched_setscheduler(struct task_struct *, int, struct sched_param *);
@@ -1011,7 +1015,6 @@
 extern void flush_thread(void);
 extern void exit_thread(void);
 
-extern void exit_mm(struct task_struct *);
 extern void exit_files(struct task_struct *);
 extern void exit_signal(struct task_struct *);
 extern void __exit_signal(struct task_struct *);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 99c97ad..0a98f5e 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -9,6 +9,17 @@
 #ifdef __KERNEL__
 
 /*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+
+/*
  * Real Time signals may be queued.
  */
 
@@ -209,6 +220,12 @@
 	INIT_LIST_HEAD(&sig->list);
 }
 
+/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */
+static inline int valid_signal(unsigned long sig)
+{
+	return sig <= _NSIG ? 1 : 0;
+}
+
 extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
 extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
 extern long do_sigpending(void __user *, unsigned long);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 22b7018..cc04f5c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -167,13 +167,14 @@
  *	@h: Transport layer header
  *	@nh: Network layer header
  *	@mac: Link layer header
- *	@dst: FIXME: Describe this field
+ *	@dst: destination entry
+ *	@sp: the security path, used for xfrm
  *	@cb: Control buffer. Free for use by every layer. Put private vars here
  *	@len: Length of actual data
  *	@data_len: Data length
  *	@mac_len: Length of link layer header
  *	@csum: Checksum
- *	@__unused: Dead field, may be reused
+ *	@local_df: allow local fragmentation
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
  *	@pkt_type: Packet class
@@ -968,6 +969,7 @@
 		kfree_skb(skb);
 }
 
+#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB
 /**
  *	__dev_alloc_skb - allocate an skbuff for sending
  *	@length: length to allocate
@@ -980,7 +982,6 @@
  *
  *	%NULL is returned in there is no free memory.
  */
-#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB
 static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
 					      int gfp_mask)
 {
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 3e3c3ab..7d66385 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -62,16 +62,9 @@
 extern int kmem_cache_destroy(kmem_cache_t *);
 extern int kmem_cache_shrink(kmem_cache_t *);
 extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast);
-#ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(kmem_cache_t *, int);
-#else
-static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int node)
-{
-	return kmem_cache_alloc(cachep, GFP_KERNEL);
-}
-#endif
 extern void kmem_cache_free(kmem_cache_t *, void *);
 extern unsigned int kmem_cache_size(kmem_cache_t *);
+extern kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags);
 
 /* Size description struct for general caches. */
 struct cache_sizes {
@@ -109,6 +102,20 @@
 extern void kfree(const void *);
 extern unsigned int ksize(const void *);
 
+#ifdef CONFIG_NUMA
+extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node);
+extern void *kmalloc_node(size_t size, int flags, int node);
+#else
+static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
+{
+	return kmem_cache_alloc(cachep, flags);
+}
+static inline void *kmalloc_node(size_t size, int flags, int node)
+{
+	return kmalloc(size, flags);
+}
+#endif
+
 extern int FASTCALL(kmem_cache_reap(int));
 extern int FASTCALL(kmem_ptr_validate(kmem_cache_t *cachep, void *ptr));
 
diff --git a/include/linux/sockios.h b/include/linux/sockios.h
index 5eb3320..e6b9d1d 100644
--- a/include/linux/sockios.h
+++ b/include/linux/sockios.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)sockios.h	1.0.2	03/09/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		This program is free software; you can redistribute it and/or
diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h
index 28d2d18..523d069 100644
--- a/include/linux/soundcard.h
+++ b/include/linux/soundcard.h
@@ -39,6 +39,13 @@
 /* In Linux we need to be prepared for cross compiling */
 #include <linux/ioctl.h>
 
+/* Endian macros. */
+#ifdef __KERNEL__
+#  include <asm/byteorder.h>
+#else
+#  include <endian.h>
+#endif
+
 /*
  *	Supported card ID numbers (Should be somewhere else?)
  */
@@ -179,13 +186,26 @@
  * Some big endian/little endian handling macros
  */
 
-#if defined(_AIX) || defined(AIX) || defined(sparc) || defined(__sparc__) || defined(HPPA) || defined(PPC) || defined(__mc68000__)
-/* Big endian machines */
-#  define _PATCHKEY(id) (0xfd00|id)
-#  define AFMT_S16_NE AFMT_S16_BE
-#else
-#  define _PATCHKEY(id) ((id<<8)|0xfd)
-#  define AFMT_S16_NE AFMT_S16_LE
+#define _LINUX_PATCHKEY_H_INDIRECT
+#include <linux/patchkey.h>
+#undef _LINUX_PATCHKEY_H_INDIRECT
+
+#if defined(__KERNEL__)
+#  if defined(__BIG_ENDIAN)
+#    define AFMT_S16_NE AFMT_S16_BE
+#  elif defined(__LITTLE_ENDIAN)
+#    define AFMT_S16_NE AFMT_S16_LE
+#  else
+#    error "could not determine byte order"
+#  endif
+#elif defined(__BYTE_ORDER)
+#  if __BYTE_ORDER == __BIG_ENDIAN
+#    define AFMT_S16_NE AFMT_S16_BE
+#  elif __BYTE_ORDER == __LITTLE_ENDIAN
+#    define AFMT_S16_NE AFMT_S16_LE
+#  else
+#    error "could not determine byte order"
+#  endif
 #endif
 
 /*
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 757cd9b..c39f6f7 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -456,8 +456,7 @@
 asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
 				unsigned nsops,
 				const struct timespec __user *timeout);
-asmlinkage long sys_shmat(int shmid, char __user *shmaddr,
-				int shmflg, unsigned long __user *addr);
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg);
 asmlinkage long sys_shmget(key_t key, size_t size, int flag);
 asmlinkage long sys_shmdt(char __user *shmaddr);
 asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 358d52b..7729981 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -643,6 +643,7 @@
 	NET_SCTP_MAX_BURST               = 12,
 	NET_SCTP_ADDIP_ENABLE		 = 13,
 	NET_SCTP_PRSCTP_ENABLE		 = 14,
+	NET_SCTP_SNDBUF_POLICY		 = 15,
 };
 
 /* /proc/sys/net/bridge */
diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h
new file mode 100644
index 0000000..964f473
--- /dev/null
+++ b/include/linux/tc_act/tc_defact.h
@@ -0,0 +1,21 @@
+#ifndef __LINUX_TC_DEF_H
+#define __LINUX_TC_DEF_H
+
+#include <linux/pkt_cls.h>
+
+struct tc_defact
+{
+	tc_gen;
+};
+                                                                                
+enum
+{
+	TCA_DEF_UNSPEC,
+	TCA_DEF_TM,
+	TCA_DEF_PARMS,
+	TCA_DEF_DATA,
+	__TCA_DEF_MAX
+};
+#define TCA_DEF_MAX (__TCA_DEF_MAX - 1)
+
+#endif
diff --git a/include/linux/trdevice.h b/include/linux/trdevice.h
index aaa1f33..99e02ef 100644
--- a/include/linux/trdevice.h
+++ b/include/linux/trdevice.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)eth.h	1.0.4	05/13/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		Relocated to include/linux where it belongs by Alan Cox 
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index f0df02a..fd2ef74 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -140,8 +140,11 @@
 	XFRM_MSG_FLUSHPOLICY,
 #define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
 
-	XFRM_MSG_MAX
+	__XFRM_MSG_MAX
 };
+#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
+
+#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
 
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
diff --git a/include/net/act_generic.h b/include/net/act_generic.h
new file mode 100644
index 0000000..95b1207
--- /dev/null
+++ b/include/net/act_generic.h
@@ -0,0 +1,142 @@
+/*
+ * include/net/act_generic.h
+ *
+*/
+#ifndef ACT_GENERIC_H
+#define ACT_GENERIC_H
+static inline int tcf_defact_release(struct tcf_defact *p, int bind)
+{
+	int ret = 0;
+	if (p) {
+		if (bind) {
+			p->bindcnt--;
+		}
+		p->refcnt--;
+		if (p->bindcnt <= 0 && p->refcnt <= 0) {
+			kfree(p->defdata);
+			tcf_hash_destroy(p);
+			ret = 1;
+		}
+	}
+	return ret;
+}
+
+static inline int
+alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
+{
+	p->defdata = kmalloc(datalen, GFP_KERNEL);
+	if (p->defdata == NULL)
+		return -ENOMEM;
+	p->datalen = datalen;
+	memcpy(p->defdata, defdata, datalen);
+	return 0;
+}
+
+static inline int
+realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
+{
+	/* safer to be just brute force for now */
+	kfree(p->defdata);
+	return alloc_defdata(p, datalen, defdata);
+}
+
+static inline int
+tcf_defact_init(struct rtattr *rta, struct rtattr *est,
+		struct tc_action *a, int ovr, int bind)
+{
+	struct rtattr *tb[TCA_DEF_MAX];
+	struct tc_defact *parm;
+	struct tcf_defact *p;
+	void *defdata;
+	u32 datalen = 0;
+	int ret = 0;
+
+	if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
+		return -EINVAL;
+
+	if (tb[TCA_DEF_PARMS - 1] == NULL || 
+	    RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
+		return -EINVAL;
+
+	parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
+	defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
+	if (defdata == NULL)
+		return -EINVAL;
+
+	datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
+	if (datalen <= 0)
+		return -EINVAL;
+
+	p = tcf_hash_check(parm->index, a, ovr, bind);
+	if (p == NULL) {
+		p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+		if (p == NULL)
+			return -ENOMEM;
+
+		ret = alloc_defdata(p, datalen, defdata);
+		if (ret < 0) {
+			kfree(p);
+			return ret;
+		}
+		ret = ACT_P_CREATED;
+	} else {
+		if (!ovr) {
+			tcf_defact_release(p, bind);
+			return -EEXIST;
+		}
+		realloc_defdata(p, datalen, defdata);
+	}
+
+	spin_lock_bh(&p->lock);
+	p->action = parm->action;
+	spin_unlock_bh(&p->lock);
+	if (ret == ACT_P_CREATED)
+		tcf_hash_insert(p);
+	return ret;
+}
+
+static inline int tcf_defact_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_defact *p = PRIV(a, defact);
+
+	if (p != NULL)
+		return tcf_defact_release(p, bind);
+	return 0;
+}
+
+static inline int
+tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+	unsigned char *b = skb->tail;
+	struct tc_defact opt;
+	struct tcf_defact *p = PRIV(a, defact);
+	struct tcf_t t;
+
+	opt.index = p->index;
+	opt.refcnt = p->refcnt - ref;
+	opt.bindcnt = p->bindcnt - bind;
+	opt.action = p->action;
+	RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
+	RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);
+	t.install = jiffies_to_clock_t(jiffies - p->tm.install);
+	t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+	t.expires = jiffies_to_clock_t(p->tm.expires);
+	RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+#define tca_use_default_ops \
+	.dump           =       tcf_defact_dump, \
+	.cleanup        =       tcf_defact_cleanup, \
+	.init           =       tcf_defact_init, \
+	.walk           =       tcf_generic_walker, \
+
+#define tca_use_default_defines(name) \
+	static u32 idx_gen; \
+	static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \
+	static DEFINE_RWLOCK(##name_lock);
+#endif /* _NET_ACT_GENERIC_H */
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 7af9a13..a0ed936 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -17,6 +17,8 @@
 
 #define IPV6_MAX_ADDRESSES		16
 
+#include <linux/in6.h>
+
 struct prefix_info {
 	__u8			type;
 	__u8			length;
@@ -43,9 +45,9 @@
 
 #ifdef __KERNEL__
 
-#include <linux/in6.h>
 #include <linux/netdevice.h>
 #include <net/if_inet6.h>
+#include <net/ipv6.h>
 
 #define IN6_ADDR_HSIZE		16
 
diff --git a/include/net/ax25.h b/include/net/ax25.h
index fb95ecb..9e6368a 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -220,6 +220,14 @@
 	}
 }
 
+static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+	skb->dev      = dev;
+	skb->pkt_type = PACKET_HOST;
+	skb->mac.raw  = skb->data;
+	return htons(ETH_P_AX25);
+}
+
 /* af_ax25.c */
 extern struct hlist_head ax25_list;
 extern spinlock_t ax25_list_lock;
@@ -305,7 +313,7 @@
 extern void ax25_output(ax25_cb *, int, struct sk_buff *);
 extern void ax25_kick(ax25_cb *);
 extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
-extern void ax25_queue_xmit(struct sk_buff *);
+extern void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev);
 extern int  ax25_check_iframes_acked(ax25_cb *, unsigned short);
 
 /* ax25_route.c */
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 3fc1924..e5ef0d15 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)icmp.h	1.0.4	05/13/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		This program is free software; you can redistribute it and/or
diff --git a/include/net/ip.h b/include/net/ip.h
index b4db137..3f63992 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)ip.h	1.0.2	05/07/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
  *
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 87c45cb..771b47e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -416,7 +416,7 @@
 						    u8 *proto);
 
 extern int			ipv6_skip_exthdr(const struct sk_buff *, int start,
-					         u8 *nexthdrp, int len);
+					         u8 *nexthdrp);
 
 extern int 			ipv6_ext_hdr(u8 nexthdr);
 
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 87496e3..fcb05a3 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -140,7 +140,7 @@
 	if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1)
 		return bound;
 	delta = delta_sec * 1000000;
-	if (delta > bound)
+	if (delta > bound || delta < 0)
 		delta = bound;
 	return delta;
 }
@@ -156,7 +156,9 @@
 		   __delta += 1000000; \
 	   case 1: \
 		   __delta += 1000000; \
-	   case 0: ; \
+	   case 0: \
+ 		   if (__delta > bound || __delta < 0) \
+ 			__delta = bound; \
 	   } \
 	   __delta; \
 })
diff --git a/include/net/route.h b/include/net/route.h
index 22da757..efe92b2 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)route.h	1.0.4	05/27/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  * Fixes:
  *		Alan Cox	:	Reformatted. Added ip_rt_local()
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 5576db5..f4fcee1 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -407,32 +407,38 @@
 	return 0;
 }
 
-/* Check VTAG of the packet matches the sender's own tag OR its peer's
- * tag and the T bit is set in the Chunk Flags.
+/* Check VTAG of the packet matches the sender's own tag and the T bit is
+ * not set, OR its peer's tag and the T bit is set in the Chunk Flags.
  */
 static inline int
 sctp_vtag_verify_either(const struct sctp_chunk *chunk,
 			const struct sctp_association *asoc)
 {
-        /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
+        /* RFC 2960 Section 8.5.1, sctpimpguide Section 2.41
 	 *
-	 * B) The receiver of a ABORT shall accept the packet if the
-	 * Verification Tag field of the packet matches its own tag OR it
-	 * is set to its peer's tag and the T bit is set in the Chunk
-	 * Flags. Otherwise, the receiver MUST silently discard the packet
-	 * and take no further action.
+	 * B) The receiver of a ABORT MUST accept the packet
+	 *    if the Verification Tag field of the packet matches its own tag
+	 *    and the T bit is not set
+	 *    OR
+	 *    it is set to its peer's tag and the T bit is set in the Chunk
+	 *    Flags.
+	 *    Otherwise, the receiver MUST silently discard the packet
+	 *    and take no further action.
 	 *
-	 * (C) The receiver of a SHUTDOWN COMPLETE shall accept the
-	 * packet if the Verification Tag field of the packet
-	 * matches its own tag OR it is set to its peer's tag and
-	 * the T bit is set in the Chunk Flags.  Otherwise, the
-	 * receiver MUST silently discard the packet and take no
-	 * further action....
-	 *
+	 * C) The receiver of a SHUTDOWN COMPLETE shall accept the packet
+	 *    if the Verification Tag field of the packet matches its own tag
+	 *    and the T bit is not set
+	 *    OR
+	 *    it is set to its peer's tag and the T bit is set in the Chunk
+	 *    Flags.
+	 *    Otherwise, the receiver MUST silently discard the packet
+	 *    and take no further action.  An endpoint MUST ignore the
+	 *    SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state.
 	 */
-        if ((ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag) ||
-	    (sctp_test_T_bit(chunk) && (ntohl(chunk->sctp_hdr->vtag)
-	    == asoc->c.peer_vtag))) {
+        if ((!sctp_test_T_bit(chunk) &&
+             (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)) ||
+	    (sctp_test_T_bit(chunk) &&
+	     (ntohl(chunk->sctp_hdr->vtag) == asoc->c.peer_vtag))) {
                 return 1;
 	}
 
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7e64cf6..6c24d9c 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -154,6 +154,13 @@
 	int max_retrans_path;
 	int max_retrans_init;
 
+	/*
+	 * Policy for preforming sctp/socket accounting
+	 * 0   - do socket level accounting, all assocs share sk_sndbuf
+	 * 1   - do sctp accounting, each asoc may use sk_sndbuf bytes
+	 */
+	int sndbuf_policy;
+
 	/* HB.interval		    - 30 seconds  */
 	int hb_interval;
 
@@ -207,6 +214,7 @@
 #define sctp_valid_cookie_life		(sctp_globals.valid_cookie_life)
 #define sctp_cookie_preserve_enable	(sctp_globals.cookie_preserve_enable)
 #define sctp_max_retrans_association	(sctp_globals.max_retrans_association)
+#define sctp_sndbuf_policy	 	(sctp_globals.sndbuf_policy)
 #define sctp_max_retrans_path		(sctp_globals.max_retrans_path)
 #define sctp_max_retrans_init		(sctp_globals.max_retrans_init)
 #define sctp_hb_interval		(sctp_globals.hb_interval)
@@ -1212,7 +1220,8 @@
 	/* Default timeouts.  */
 	int timeouts[SCTP_NUM_TIMEOUT_TYPES];
 
-	/* Various thresholds.	*/
+	/* sendbuf acct. policy.	*/
+	__u32 sndbuf_policy;
 
 	/* Name for debugging output... */
 	char *debug_name;
diff --git a/include/net/sock.h b/include/net/sock.h
index be81cab..a9ef3a6 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)sock.h	1.0.4	05/13/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
  *		Florian La Roche <flla@stud.uni-sb.de>
@@ -90,17 +90,17 @@
 struct sock;
 
 /**
-  *	struct sock_common - minimal network layer representation of sockets
-  *	@skc_family - network address family
-  *	@skc_state - Connection state
-  *	@skc_reuse - %SO_REUSEADDR setting
-  *	@skc_bound_dev_if - bound device index if != 0
-  *	@skc_node - main hash linkage for various protocol lookup tables
-  *	@skc_bind_node - bind hash linkage for various protocol lookup tables
-  *	@skc_refcnt - reference count
-  *
-  *	This is the minimal network layer representation of sockets, the header
-  *	for struct sock and struct tcp_tw_bucket.
+ *	struct sock_common - minimal network layer representation of sockets
+ *	@skc_family: network address family
+ *	@skc_state: Connection state
+ *	@skc_reuse: %SO_REUSEADDR setting
+ *	@skc_bound_dev_if: bound device index if != 0
+ *	@skc_node: main hash linkage for various protocol lookup tables
+ *	@skc_bind_node: bind hash linkage for various protocol lookup tables
+ *	@skc_refcnt: reference count
+ *
+ *	This is the minimal network layer representation of sockets, the header
+ *	for struct sock and struct tcp_tw_bucket.
   */
 struct sock_common {
 	unsigned short		skc_family;
@@ -114,60 +114,62 @@
 
 /**
   *	struct sock - network layer representation of sockets
-  *	@__sk_common - shared layout with tcp_tw_bucket
-  *	@sk_shutdown - mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
-  *	@sk_userlocks - %SO_SNDBUF and %SO_RCVBUF settings
-  *	@sk_lock -	synchronizer
-  *	@sk_rcvbuf - size of receive buffer in bytes
-  *	@sk_sleep - sock wait queue
-  *	@sk_dst_cache - destination cache
-  *	@sk_dst_lock - destination cache lock
-  *	@sk_policy - flow policy
-  *	@sk_rmem_alloc - receive queue bytes committed
-  *	@sk_receive_queue - incoming packets
-  *	@sk_wmem_alloc - transmit queue bytes committed
-  *	@sk_write_queue - Packet sending queue
-  *	@sk_omem_alloc - "o" is "option" or "other"
-  *	@sk_wmem_queued - persistent queue size
-  *	@sk_forward_alloc - space allocated forward
-  *	@sk_allocation - allocation mode
-  *	@sk_sndbuf - size of send buffer in bytes
-  *	@sk_flags - %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings
-  *	@sk_no_check - %SO_NO_CHECK setting, wether or not checkup packets
-  *	@sk_route_caps - route capabilities (e.g. %NETIF_F_TSO)
-  *	@sk_lingertime - %SO_LINGER l_linger setting
-  *	@sk_hashent - hash entry in several tables (e.g. tcp_ehash)
-  *	@sk_backlog - always used with the per-socket spinlock held
-  *	@sk_callback_lock - used with the callbacks in the end of this struct
-  *	@sk_error_queue - rarely used
-  *	@sk_prot - protocol handlers inside a network family
-  *	@sk_err - last error
-  *	@sk_err_soft - errors that don't cause failure but are the cause of a persistent failure not just 'timed out'
-  *	@sk_ack_backlog - current listen backlog
-  *	@sk_max_ack_backlog - listen backlog set in listen()
-  *	@sk_priority - %SO_PRIORITY setting
-  *	@sk_type - socket type (%SOCK_STREAM, etc)
-  *	@sk_protocol - which protocol this socket belongs in this network family
-  *	@sk_peercred - %SO_PEERCRED setting
-  *	@sk_rcvlowat - %SO_RCVLOWAT setting
-  *	@sk_rcvtimeo - %SO_RCVTIMEO setting
-  *	@sk_sndtimeo - %SO_SNDTIMEO setting
-  *	@sk_filter - socket filtering instructions
-  *	@sk_protinfo - private area, net family specific, when not using slab
-  *	@sk_timer - sock cleanup timer
-  *	@sk_stamp - time stamp of last packet received
-  *	@sk_socket - Identd and reporting IO signals
-  *	@sk_user_data - RPC layer private data
-  *	@sk_sndmsg_page - cached page for sendmsg
-  *	@sk_sndmsg_off - cached offset for sendmsg
-  *	@sk_send_head - front of stuff to transmit
-  *	@sk_write_pending - a write to stream socket waits to start
-  *	@sk_state_change - callback to indicate change in the state of the sock
-  *	@sk_data_ready - callback to indicate there is data to be processed
-  *	@sk_write_space - callback to indicate there is bf sending space available
-  *	@sk_error_report - callback to indicate errors (e.g. %MSG_ERRQUEUE)
-  *	@sk_backlog_rcv - callback to process the backlog
-  *	@sk_destruct - called at sock freeing time, i.e. when all refcnt == 0
+  *	@__sk_common: shared layout with tcp_tw_bucket
+  *	@sk_shutdown: mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
+  *	@sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings
+  *	@sk_lock:	synchronizer
+  *	@sk_rcvbuf: size of receive buffer in bytes
+  *	@sk_sleep: sock wait queue
+  *	@sk_dst_cache: destination cache
+  *	@sk_dst_lock: destination cache lock
+  *	@sk_policy: flow policy
+  *	@sk_rmem_alloc: receive queue bytes committed
+  *	@sk_receive_queue: incoming packets
+  *	@sk_wmem_alloc: transmit queue bytes committed
+  *	@sk_write_queue: Packet sending queue
+  *	@sk_omem_alloc: "o" is "option" or "other"
+  *	@sk_wmem_queued: persistent queue size
+  *	@sk_forward_alloc: space allocated forward
+  *	@sk_allocation: allocation mode
+  *	@sk_sndbuf: size of send buffer in bytes
+  *	@sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings
+  *	@sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+  *	@sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
+  *	@sk_lingertime: %SO_LINGER l_linger setting
+  *	@sk_hashent: hash entry in several tables (e.g. tcp_ehash)
+  *	@sk_backlog: always used with the per-socket spinlock held
+  *	@sk_callback_lock: used with the callbacks in the end of this struct
+  *	@sk_error_queue: rarely used
+  *	@sk_prot: protocol handlers inside a network family
+  *	@sk_prot_creator: sk_prot of original sock creator (see ipv6_setsockopt, IPV6_ADDRFORM for instance)
+  *	@sk_err: last error
+  *	@sk_err_soft: errors that don't cause failure but are the cause of a persistent failure not just 'timed out'
+  *	@sk_ack_backlog: current listen backlog
+  *	@sk_max_ack_backlog: listen backlog set in listen()
+  *	@sk_priority: %SO_PRIORITY setting
+  *	@sk_type: socket type (%SOCK_STREAM, etc)
+  *	@sk_protocol: which protocol this socket belongs in this network family
+  *	@sk_peercred: %SO_PEERCRED setting
+  *	@sk_rcvlowat: %SO_RCVLOWAT setting
+  *	@sk_rcvtimeo: %SO_RCVTIMEO setting
+  *	@sk_sndtimeo: %SO_SNDTIMEO setting
+  *	@sk_filter: socket filtering instructions
+  *	@sk_protinfo: private area, net family specific, when not using slab
+  *	@sk_timer: sock cleanup timer
+  *	@sk_stamp: time stamp of last packet received
+  *	@sk_socket: Identd and reporting IO signals
+  *	@sk_user_data: RPC layer private data
+  *	@sk_sndmsg_page: cached page for sendmsg
+  *	@sk_sndmsg_off: cached offset for sendmsg
+  *	@sk_send_head: front of stuff to transmit
+  *	@sk_security: used by security modules
+  *	@sk_write_pending: a write to stream socket waits to start
+  *	@sk_state_change: callback to indicate change in the state of the sock
+  *	@sk_data_ready: callback to indicate there is data to be processed
+  *	@sk_write_space: callback to indicate there is bf sending space available
+  *	@sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE)
+  *	@sk_backlog_rcv: callback to process the backlog
+  *	@sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
  */
 struct sock {
 	/*
@@ -217,6 +219,7 @@
 	} sk_backlog;
 	struct sk_buff_head	sk_error_queue;
 	struct proto		*sk_prot;
+	struct proto		*sk_prot_creator;
 	rwlock_t		sk_callback_lock;
 	int			sk_err,
 				sk_err_soft;
@@ -1223,8 +1226,8 @@
 
 /**
  * sk_eat_skb - Release a skb if it is no longer needed
- * @sk - socket to eat this skb from
- * @skb - socket buffer to eat
+ * @sk: socket to eat this skb from
+ * @skb: socket buffer to eat
  *
  * This routine must be called with interrupts disabled or with the socket
  * locked so that the sk_buff queue operation is ok.
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
new file mode 100644
index 0000000..463aa67
--- /dev/null
+++ b/include/net/tc_act/tc_defact.h
@@ -0,0 +1,13 @@
+#ifndef __NET_TC_DEF_H
+#define __NET_TC_DEF_H
+
+#include <net/act_api.h>
+
+struct tcf_defact
+{
+	tca_gen(defact);
+	u32     datalen;
+	void    *defdata;
+};
+
+#endif
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 503810a..e71f8ba 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)tcp.h	1.0.5	05/23/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  *		This program is free software; you can redistribute it and/or
@@ -1417,19 +1417,20 @@
 		  tcp_minshall_check(tp))));
 }
 
-extern void tcp_set_skb_tso_segs(struct sk_buff *, unsigned int);
+extern void tcp_set_skb_tso_segs(struct sock *, struct sk_buff *);
 
 /* This checks if the data bearing packet SKB (usually sk->sk_send_head)
  * should be put on the wire right now.
  */
-static __inline__ int tcp_snd_test(const struct tcp_sock *tp, 
+static __inline__ int tcp_snd_test(struct sock *sk,
 				   struct sk_buff *skb,
 				   unsigned cur_mss, int nonagle)
 {
+	struct tcp_sock *tp = tcp_sk(sk);
 	int pkts = tcp_skb_pcount(skb);
 
 	if (!pkts) {
-		tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+		tcp_set_skb_tso_segs(sk, skb);
 		pkts = tcp_skb_pcount(skb);
 	}
 
@@ -1490,7 +1491,7 @@
 	if (skb) {
 		if (!tcp_skb_is_last(sk, skb))
 			nonagle = TCP_NAGLE_PUSH;
-		if (!tcp_snd_test(tp, skb, cur_mss, nonagle) ||
+		if (!tcp_snd_test(sk, skb, cur_mss, nonagle) ||
 		    tcp_write_xmit(sk, nonagle))
 			tcp_check_probe_timer(sk, tp);
 	}
@@ -1508,7 +1509,7 @@
 	struct sk_buff *skb = sk->sk_send_head;
 
 	return (skb &&
-		tcp_snd_test(tp, skb, tcp_current_mss(sk, 1),
+		tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
 			     tcp_skb_is_last(sk, skb) ? TCP_NAGLE_PUSH : tp->nonagle));
 }
 
diff --git a/include/net/udp.h b/include/net/udp.h
index c496d10..ac229b7 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)udp.h	1.0.2	05/07/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  * Fixes:
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 73e9a8c..e142a25 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1,6 +1,7 @@
 #ifndef _NET_XFRM_H
 #define _NET_XFRM_H
 
+#include <linux/compiler.h>
 #include <linux/xfrm.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
@@ -516,6 +517,15 @@
 	u32 child_mtu_cached;
 };
 
+static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
+{
+	dst_release(xdst->route);
+	if (likely(xdst->u.dst.xfrm))
+		xfrm_state_put(xdst->u.dst.xfrm);
+}
+
+extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
+
 /* Decapsulation state, used by the input to store data during
  * decapsulation procedure, to be used later (during the policy
  * check
diff --git a/include/video/edid.h b/include/video/edid.h
index abc1b48..b913f19 100644
--- a/include/video/edid.h
+++ b/include/video/edid.h
@@ -4,9 +4,6 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
-#ifdef CONFIG_PPC_OF
-#include <linux/pci.h>
-#endif
 
 #ifdef CONFIG_X86
 struct edid_info {
@@ -14,14 +11,8 @@
 };
 
 extern struct edid_info edid_info;
-extern char *get_EDID_from_BIOS(void *);
-
 #endif /* CONFIG_X86 */
 
-#ifdef CONFIG_PPC_OF
-extern char *get_EDID_from_OF(struct pci_dev *pdev);
-#endif
-
 #endif /* __KERNEL__ */
 
 #endif /* __linux_video_edid_h__ */
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index a896e44..0423767 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -99,6 +99,8 @@
 #define MISCINIT1_2DBLOCK_DIS           BIT(15)
 #define DRAMINIT0_SGRAM_NUM             BIT(26)
 #define DRAMINIT0_SGRAM_TYPE            BIT(27)
+#define DRAMINIT0_SGRAM_TYPE_MASK       (BIT(27)|BIT(28)|BIT(29))
+#define DRAMINIT0_SGRAM_TYPE_SHIFT      27
 #define DRAMINIT1_MEM_SDRAM             BIT(30)
 #define VGAINIT0_VGA_DISABLE            BIT(0)
 #define VGAINIT0_EXT_TIMING             BIT(1)
diff --git a/init/Kconfig b/init/Kconfig
index abe2682..d920bae 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -173,7 +173,7 @@
 
 config AUDITSYSCALL
 	bool "Enable system-call auditing support"
-	depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64)
+	depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64 || UML)
 	default y if SECURITY_SELINUX
 	help
 	  Enable low-overhead system-call auditing infrastructure that
@@ -275,6 +275,27 @@
 	   reported.  KALLSYMS_EXTRA_PASS is only a temporary workaround while
 	   you wait for kallsyms to be fixed.
 
+
+config PRINTK
+	default y
+	bool "Enable support for printk" if EMBEDDED
+	help
+	  This option enables normal printk support. Removing it
+	  eliminates most of the message strings from the kernel image
+	  and makes the kernel more or less silent. As this makes it
+	  very difficult to diagnose system problems, saying N here is
+	  strongly discouraged.
+
+config BUG
+	bool "BUG() support" if EMBEDDED
+	default y
+	help
+          Disabling this option eliminates support for BUG and WARN, reducing
+          the size of your kernel image and potentially quietly ignoring
+          numerous fatal conditions. You should only consider disabling this
+          option for embedded systems with no facilities for reporting errors.
+          Just say Y.
+
 config BASE_FULL
 	default y
 	bool "Enable full-sized data structures for core" if EMBEDDED
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index cb0cd3c..0acf245 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -23,6 +23,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/syscalls.h>
+#include <linux/signal.h>
 #include <net/sock.h>
 #include "util.h"
 
@@ -767,7 +768,7 @@
 	list_del(&receiver->list);
 	receiver->state = STATE_PENDING;
 	wake_up_process(receiver->task);
-	wmb();
+	smp_wmb();
 	receiver->state = STATE_READY;
 }
 
@@ -786,7 +787,7 @@
 	list_del(&sender->list);
 	sender->state = STATE_PENDING;
 	wake_up_process(sender->task);
-	wmb();
+	smp_wmb();
 	sender->state = STATE_READY;
 }
 
@@ -976,8 +977,7 @@
 			     notification.sigev_notify != SIGEV_THREAD))
 			return -EINVAL;
 		if (notification.sigev_notify == SIGEV_SIGNAL &&
-			(notification.sigev_signo < 0 ||
-			 notification.sigev_signo > _NSIG)) {
+			!valid_signal(notification.sigev_signo)) {
 			return -EINVAL;
 		}
 		if (notification.sigev_notify == SIGEV_THREAD) {
diff --git a/ipc/shm.c b/ipc/shm.c
index 06cd5c91..cce02243 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -28,6 +28,8 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/audit.h>
+#include <linux/ptrace.h>
+
 #include <asm/uaccess.h>
 
 #include "util.h"
@@ -771,6 +773,18 @@
 	return err;
 }
 
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
+{
+	unsigned long ret;
+	long err;
+
+	err = do_shmat(shmid, shmaddr, shmflg, &ret);
+	if (err)
+		return err;
+	force_successful_syscall_return();
+	return (long)ret;
+}
+
 /*
  * detach and kill segment if marked destroyed.
  * The work is done in shm_close.
diff --git a/kernel/Makefile b/kernel/Makefile
index eb88b44..b01d26f 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -29,7 +29,7 @@
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_SECCOMP) += seccomp.o
 
-ifneq ($(CONFIG_IA64),y)
+ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
 # needed for x86 only.  Why this used to be enabled for all architectures is beyond
 # me.  I suspect most platforms don't need this, but until we know that for sure
diff --git a/kernel/audit.c b/kernel/audit.c
index 0f84dd7..9c4f1af 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1,4 +1,4 @@
-/* audit.c -- Auditing support -*- linux-c -*-
+/* audit.c -- Auditing support
  * Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
  * System-call specific features have moved to auditsc.c
  *
@@ -38,7 +38,7 @@
  *	  6) Support low-overhead kernel-based filtering to minimize the
  *	     information that must be passed to user-space.
  *
- * Example user-space utilities: http://people.redhat.com/faith/audit/
+ * Example user-space utilities: http://people.redhat.com/sgrubb/audit/
  */
 
 #include <linux/init.h>
@@ -142,7 +142,6 @@
 	int		     total;
 	int		     type;
 	int		     pid;
-	int		     count; /* Times requeued */
 };
 
 void audit_set_type(struct audit_buffer *ab, int type)
@@ -239,36 +238,36 @@
 
 }
 
-static int audit_set_rate_limit(int limit)
+static int audit_set_rate_limit(int limit, uid_t loginuid)
 {
 	int old		 = audit_rate_limit;
 	audit_rate_limit = limit;
-	audit_log(current->audit_context, "audit_rate_limit=%d old=%d",
-		  audit_rate_limit, old);
+	audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
+			audit_rate_limit, old, loginuid);
 	return old;
 }
 
-static int audit_set_backlog_limit(int limit)
+static int audit_set_backlog_limit(int limit, uid_t loginuid)
 {
 	int old		 = audit_backlog_limit;
 	audit_backlog_limit = limit;
-	audit_log(current->audit_context, "audit_backlog_limit=%d old=%d",
-		  audit_backlog_limit, old);
+	audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
+			audit_backlog_limit, old, loginuid);
 	return old;
 }
 
-static int audit_set_enabled(int state)
+static int audit_set_enabled(int state, uid_t loginuid)
 {
 	int old		 = audit_enabled;
 	if (state != 0 && state != 1)
 		return -EINVAL;
 	audit_enabled = state;
-	audit_log(current->audit_context, "audit_enabled=%d old=%d",
-		  audit_enabled, old);
+	audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
+		  audit_enabled, old, loginuid);
 	return old;
 }
 
-static int audit_set_failure(int state)
+static int audit_set_failure(int state, uid_t loginuid)
 {
 	int old		 = audit_failure;
 	if (state != AUDIT_FAIL_SILENT
@@ -276,8 +275,8 @@
 	    && state != AUDIT_FAIL_PANIC)
 		return -EINVAL;
 	audit_failure = state;
-	audit_log(current->audit_context, "audit_failure=%d old=%d",
-		  audit_failure, old);
+	audit_log(NULL, "audit_failure=%d old=%d by auid %u",
+		  audit_failure, old, loginuid);
 	return old;
 }
 
@@ -344,6 +343,7 @@
 	int			err;
 	struct audit_buffer	*ab;
 	u16			msg_type = nlh->nlmsg_type;
+	uid_t			loginuid; /* loginuid of sender */
 
 	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
 	if (err)
@@ -351,6 +351,7 @@
 
 	pid  = NETLINK_CREDS(skb)->pid;
 	uid  = NETLINK_CREDS(skb)->uid;
+	loginuid = NETLINK_CB(skb).loginuid;
 	seq  = nlh->nlmsg_seq;
 	data = NLMSG_DATA(nlh);
 
@@ -371,34 +372,36 @@
 			return -EINVAL;
 		status_get   = (struct audit_status *)data;
 		if (status_get->mask & AUDIT_STATUS_ENABLED) {
-			err = audit_set_enabled(status_get->enabled);
+			err = audit_set_enabled(status_get->enabled, loginuid);
 			if (err < 0) return err;
 		}
 		if (status_get->mask & AUDIT_STATUS_FAILURE) {
-			err = audit_set_failure(status_get->failure);
+			err = audit_set_failure(status_get->failure, loginuid);
 			if (err < 0) return err;
 		}
 		if (status_get->mask & AUDIT_STATUS_PID) {
 			int old   = audit_pid;
 			audit_pid = status_get->pid;
-			audit_log(current->audit_context,
-				  "audit_pid=%d old=%d", audit_pid, old);
+			audit_log(NULL, "audit_pid=%d old=%d by auid %u",
+				  audit_pid, old, loginuid);
 		}
 		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
-			audit_set_rate_limit(status_get->rate_limit);
+			audit_set_rate_limit(status_get->rate_limit, loginuid);
 		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
-			audit_set_backlog_limit(status_get->backlog_limit);
+			audit_set_backlog_limit(status_get->backlog_limit,
+							loginuid);
 		break;
 	case AUDIT_USER:
 		ab = audit_log_start(NULL);
 		if (!ab)
 			break;	/* audit_panic has been called */
 		audit_log_format(ab,
-				 "user pid=%d uid=%d length=%d msg='%.1024s'",
+				 "user pid=%d uid=%d length=%d loginuid=%u"
+				 " msg='%.1024s'",
 				 pid, uid,
 				 (int)(nlh->nlmsg_len
 				       - ((char *)data - (char *)nlh)),
-				 (char *)data);
+				 loginuid, (char *)data);
 		ab->type = AUDIT_USER;
 		ab->pid  = pid;
 		audit_log_end(ab);
@@ -411,7 +414,7 @@
 	case AUDIT_LIST:
 #ifdef CONFIG_AUDITSYSCALL
 		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
-					   uid, seq, data);
+					   uid, seq, data, loginuid);
 #else
 		err = -EOPNOTSUPP;
 #endif
@@ -427,7 +430,7 @@
 /* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
  * processed by audit_receive_msg.  Malformed skbs with wrong length are
  * discarded silently.  */
-static int audit_receive_skb(struct sk_buff *skb)
+static void audit_receive_skb(struct sk_buff *skb)
 {
 	int		err;
 	struct nlmsghdr	*nlh;
@@ -436,7 +439,7 @@
 	while (skb->len >= NLMSG_SPACE(0)) {
 		nlh = (struct nlmsghdr *)skb->data;
 		if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
-			return 0;
+			return;
 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
 		if (rlen > skb->len)
 			rlen = skb->len;
@@ -446,23 +449,20 @@
 			netlink_ack(skb, nlh, 0);
 		skb_pull(skb, rlen);
 	}
-	return 0;
 }
 
 /* Receive messages from netlink socket. */
 static void audit_receive(struct sock *sk, int length)
 {
 	struct sk_buff  *skb;
+	unsigned int qlen;
 
-	if (down_trylock(&audit_netlink_sem))
-		return;
+	down(&audit_netlink_sem);
 
-				/* FIXME: this must not cause starvation */
-	while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
-		if (audit_receive_skb(skb) && skb->len)
-			skb_queue_head(&sk->sk_receive_queue, skb);
-		else
-			kfree_skb(skb);
+	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+		skb = skb_dequeue(&sk->sk_receive_queue);
+		audit_receive_skb(skb);
+		kfree_skb(skb);
 	}
 	up(&audit_netlink_sem);
 }
@@ -483,7 +483,7 @@
 	if (ab->len == 0)
 		return;
 
-	skb = skb_peek(&ab->sklist);
+	skb = skb_peek_tail(&ab->sklist);
 	if (!skb || skb_tailroom(skb) <= ab->len + extra) {
 		skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
 		if (!skb) {
@@ -522,9 +522,9 @@
 			retval = netlink_unicast(audit_sock, skb, audit_pid,
 						 MSG_DONTWAIT);
 		}
-		if (retval == -EAGAIN && ab->count < 5) {
-			++ab->count;
-			skb_queue_tail(&ab->sklist, skb);
+		if (retval == -EAGAIN &&
+		    (atomic_read(&audit_backlog)) < audit_backlog_limit) {
+			skb_queue_head(&ab->sklist, skb);
 			audit_log_end_irq(ab);
 			return 1;
 		}
@@ -540,8 +540,8 @@
 		if (!audit_pid) { /* No daemon */
 			int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
 			int len    = skb->len - offset;
-			printk(KERN_ERR "%*.*s\n",
-			       len, len, skb->data + offset);
+			skb->data[offset + len] = '\0';
+			printk(KERN_ERR "%s\n", skb->data + offset);
 		}
 		kfree_skb(skb);
 		ab->nlh = NULL;
@@ -620,7 +620,7 @@
 	struct audit_buffer	*ab	= NULL;
 	unsigned long		flags;
 	struct timespec		t;
-	int			serial	= 0;
+	unsigned int		serial;
 
 	if (!audit_initialized)
 		return NULL;
@@ -662,15 +662,16 @@
 	ab->total = 0;
 	ab->type  = AUDIT_KERNEL;
 	ab->pid   = 0;
-	ab->count = 0;
 
 #ifdef CONFIG_AUDITSYSCALL
 	if (ab->ctx)
 		audit_get_stamp(ab->ctx, &t, &serial);
 	else
 #endif
+	{
 		t = CURRENT_TIME;
-
+		serial = 0;
+	}
 	audit_log_format(ab, "audit(%lu.%03lu:%u): ",
 			 t.tv_sec, t.tv_nsec/1000000, serial);
 	return ab;
@@ -720,6 +721,29 @@
 	va_end(args);
 }
 
+void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len)
+{
+	int i;
+
+	for (i=0; i<len; i++)
+		audit_log_format(ab, "%02x", buf[i]);
+}
+
+void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+{
+	const unsigned char *p = string;
+
+	while (*p) {
+		if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) {
+			audit_log_hex(ab, string, strlen(string));
+			return;
+		}
+		p++;
+	}
+	audit_log_format(ab, "\"%s\"", string);
+}
+
+
 /* This is a helper-function to print the d_path without using a static
  * buffer or allocating another buffer in addition to the one in
  * audit_buffer. */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 6f19313..37b3ac9 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1,4 +1,4 @@
-/* auditsc.c -- System-call auditing support -*- linux-c -*-
+/* auditsc.c -- System-call auditing support
  * Handles all system-call specific auditing features.
  *
  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
@@ -123,7 +123,7 @@
 	int		    major;      /* syscall number */
 	unsigned long	    argv[4];    /* syscall arguments */
 	int		    return_valid; /* return code is valid */
-	int		    return_code;/* syscall return code */
+	long		    return_code;/* syscall return code */
 	int		    auditable;  /* 1 if record should be written */
 	int		    name_count;
 	struct audit_names  names[AUDIT_NAMES];
@@ -135,6 +135,7 @@
 	uid_t		    uid, euid, suid, fsuid;
 	gid_t		    gid, egid, sgid, fsgid;
 	unsigned long	    personality;
+	int		    arch;
 
 #if AUDIT_DEBUG
 	int		    put_count;
@@ -250,7 +251,8 @@
 	return 0;
 }
 
-int audit_receive_filter(int type, int pid, int uid, int seq, void *data)
+int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
+							uid_t loginuid)
 {
 	u32		   flags;
 	struct audit_entry *entry;
@@ -285,6 +287,7 @@
 			err = audit_add_rule(entry, &audit_entlist);
 		if (!err && (flags & AUDIT_AT_EXIT))
 			err = audit_add_rule(entry, &audit_extlist);
+		audit_log(NULL, "auid %u added an audit rule\n", loginuid);
 		break;
 	case AUDIT_DEL:
 		flags =((struct audit_rule *)data)->flags;
@@ -294,6 +297,7 @@
 			err = audit_del_rule(data, &audit_entlist);
 		if (!err && (flags & AUDIT_AT_EXIT))
 			err = audit_del_rule(data, &audit_extlist);
+		audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
 		break;
 	default:
 		return -EINVAL;
@@ -348,6 +352,10 @@
 		case AUDIT_PERS:
 			result = (tsk->personality == value);
 			break;
+		case AUDIT_ARCH:
+			if (ctx) 
+				result = (ctx->arch == value);
+			break;
 
 		case AUDIT_EXIT:
 			if (ctx && ctx->return_valid)
@@ -355,7 +363,7 @@
 			break;
 		case AUDIT_SUCCESS:
 			if (ctx && ctx->return_valid)
-				result = (ctx->return_code >= 0);
+				result = (ctx->return_valid == AUDITSC_SUCCESS);
 			break;
 		case AUDIT_DEVMAJOR:
 			if (ctx) {
@@ -648,8 +656,11 @@
 	audit_log_format(ab, "syscall=%d", context->major);
 	if (context->personality != PER_LINUX)
 		audit_log_format(ab, " per=%lx", context->personality);
+	audit_log_format(ab, " arch=%x", context->arch);
 	if (context->return_valid)
-		audit_log_format(ab, " exit=%d", context->return_code);
+		audit_log_format(ab, " success=%s exit=%ld", 
+				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
+				 context->return_code);
 	audit_log_format(ab,
 		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
 		  " pid=%d loginuid=%d uid=%d gid=%d"
@@ -696,9 +707,10 @@
 		if (!ab)
 			continue; /* audit_panic has been called */
 		audit_log_format(ab, "item=%d", i);
-		if (context->names[i].name)
-			audit_log_format(ab, " name=%s",
-					 context->names[i].name);
+		if (context->names[i].name) {
+			audit_log_format(ab, " name=");
+			audit_log_untrustedstring(ab, context->names[i].name);
+		}
 		if (context->names[i].ino != (unsigned long)-1)
 			audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
 					     " uid=%d gid=%d rdev=%02x:%02x",
@@ -772,7 +784,7 @@
  * then the record will be written at syscall exit time (otherwise, it
  * will only be written if another part of the kernel requests that it
  * be written). */
-void audit_syscall_entry(struct task_struct *tsk, int major,
+void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
 			 unsigned long a1, unsigned long a2,
 			 unsigned long a3, unsigned long a4)
 {
@@ -826,6 +838,7 @@
 	if (!audit_enabled)
 		return;
 
+	context->arch	    = arch;
 	context->major      = major;
 	context->argv[0]    = a1;
 	context->argv[1]    = a2;
@@ -849,13 +862,13 @@
  * filtering, or because some other part of the kernel write an audit
  * message), then write out the syscall information.  In call cases,
  * free the names stored from getname(). */
-void audit_syscall_exit(struct task_struct *tsk, int return_code)
+void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
 {
 	struct audit_context *context;
 
 	get_task_struct(tsk);
 	task_lock(tsk);
-	context = audit_get_context(tsk, 1, return_code);
+	context = audit_get_context(tsk, valid, return_code);
 	task_unlock(tsk);
 
 	/* Not having a context here is ok, since the parent may have
@@ -868,6 +881,7 @@
 
 	context->in_syscall = 0;
 	context->auditable  = 0;
+
 	if (context->previous) {
 		struct audit_context *new_context = context->previous;
 		context->previous  = NULL;
@@ -981,7 +995,7 @@
 }
 
 void audit_get_stamp(struct audit_context *ctx,
-		     struct timespec *t, int *serial)
+		     struct timespec *t, unsigned int *serial)
 {
 	if (ctx) {
 		t->tv_sec  = ctx->ctime.tv_sec;
@@ -996,20 +1010,21 @@
 
 extern int audit_set_type(struct audit_buffer *ab, int type);
 
-int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid)
+int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
-	if (ctx) {
+	if (task->audit_context) {
 		struct audit_buffer *ab;
 
 		ab = audit_log_start(NULL);
 		if (ab) {
 			audit_log_format(ab, "login pid=%d uid=%u "
 				"old loginuid=%u new loginuid=%u",
-				ctx->pid, ctx->uid, ctx->loginuid, loginuid);
+				task->pid, task->uid, 
+				task->audit_context->loginuid, loginuid);
 			audit_set_type(ab, AUDIT_LOGIN);
 			audit_log_end(ab);
 		}
-		ctx->loginuid = loginuid;
+		task->audit_context->loginuid = loginuid;
 	}
 	return 0;
 }
diff --git a/kernel/exit.c b/kernel/exit.c
index 39d35935..edaa50b 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -27,6 +27,7 @@
 #include <linux/mempolicy.h>
 #include <linux/cpuset.h>
 #include <linux/syscalls.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -38,6 +39,8 @@
 
 int getrusage(struct task_struct *, int, struct rusage __user *);
 
+static void exit_mm(struct task_struct * tsk);
+
 static void __unhash_process(struct task_struct *p)
 {
 	nr_threads--;
@@ -209,7 +212,7 @@
 }
 
 /**
- * reparent_to_init() - Reparent the calling kernel thread to the init task.
+ * reparent_to_init - Reparent the calling kernel thread to the init task.
  *
  * If a kernel thread is launched as a result of a system call, or if
  * it ever exits, it should generally reparent itself to init so that
@@ -277,7 +280,7 @@
  */
 int allow_signal(int sig)
 {
-	if (sig < 1 || sig > _NSIG)
+	if (!valid_signal(sig) || sig < 1)
 		return -EINVAL;
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -298,7 +301,7 @@
 
 int disallow_signal(int sig)
 {
-	if (sig < 1 || sig > _NSIG)
+	if (!valid_signal(sig) || sig < 1)
 		return -EINVAL;
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -473,7 +476,7 @@
  * Turn us into a lazy TLB process if we
  * aren't already..
  */
-void exit_mm(struct task_struct * tsk)
+static void exit_mm(struct task_struct * tsk)
 {
 	struct mm_struct *mm = tsk->mm;
 
@@ -517,8 +520,6 @@
 	 */
 	BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE);
 	p->real_parent = reaper;
-	if (p->parent == p->real_parent)
-		BUG();
 }
 
 static inline void reparent_thread(task_t *p, task_t *father, int traced)
@@ -845,6 +846,8 @@
 	for (;;) ;
 }
 
+EXPORT_SYMBOL_GPL(do_exit);
+
 NORET_TYPE void complete_and_exit(struct completion *comp, long code)
 {
 	if (comp)
diff --git a/kernel/futex.c b/kernel/futex.c
index 7b54a67..c7130f8 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -39,6 +39,7 @@
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
+#include <linux/signal.h>
 
 #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
@@ -654,7 +655,7 @@
 	int ret, err;
 
 	ret = -EINVAL;
-	if (signal < 0 || signal > _NSIG)
+	if (!valid_signal(signal))
 		goto out;
 
 	ret = get_unused_fd();
diff --git a/kernel/itimer.c b/kernel/itimer.c
index e9a40e9..1dc988e 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -123,7 +123,11 @@
 		return;
 	if (interval > (unsigned long) LONG_MAX)
 		interval = LONG_MAX;
-	p->signal->real_timer.expires = jiffies + interval;
+	/* the "+ 1" below makes sure that the timer doesn't go off before
+	 * the interval requested. This could happen if
+	 * time requested % (usecs per jiffy) is more than the usecs left
+	 * in the current jiffy */
+	p->signal->real_timer.expires = jiffies + interval + 1;
 	add_timer(&p->signal->real_timer);
 }
 
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 1627f8d..13bcec1 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -46,6 +46,14 @@
 	return 0;
 }
 
+static inline int is_kernel_extratext(unsigned long addr)
+{
+	if (addr >= (unsigned long)_sextratext
+	    && addr <= (unsigned long)_eextratext)
+		return 1;
+	return 0;
+}
+
 static inline int is_kernel_text(unsigned long addr)
 {
 	if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)
@@ -169,8 +177,9 @@
 	namebuf[0] = 0;
 
 	if ((all_var && is_kernel(addr)) ||
-	    (!all_var && (is_kernel_text(addr) || is_kernel_inittext(addr)))) {
-		unsigned long symbol_end=0;
+	    (!all_var && (is_kernel_text(addr) || is_kernel_inittext(addr) ||
+				is_kernel_extratext(addr)))) {
+		unsigned long symbol_end = 0;
 
 		/* do a binary search on the sorted kallsyms_addresses array */
 		low = 0;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1d5dd13..037142b7 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -44,6 +44,7 @@
 
 unsigned int kprobe_cpu = NR_CPUS;
 static DEFINE_SPINLOCK(kprobe_lock);
+static struct kprobe *curr_kprobe;
 
 /* Locks kprobe: irqs must be disabled */
 void lock_kprobes(void)
@@ -73,22 +74,139 @@
 	return NULL;
 }
 
+/*
+ * Aggregate handlers for multiple kprobes support - these handlers
+ * take care of invoking the individual kprobe handlers on p->list
+ */
+int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kprobe *kp;
+
+	list_for_each_entry(kp, &p->list, list) {
+		if (kp->pre_handler) {
+			curr_kprobe = kp;
+			kp->pre_handler(kp, regs);
+			curr_kprobe = NULL;
+		}
+	}
+	return 0;
+}
+
+void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
+		unsigned long flags)
+{
+	struct kprobe *kp;
+
+	list_for_each_entry(kp, &p->list, list) {
+		if (kp->post_handler) {
+			curr_kprobe = kp;
+			kp->post_handler(kp, regs, flags);
+			curr_kprobe = NULL;
+		}
+	}
+	return;
+}
+
+int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr)
+{
+	/*
+	 * if we faulted "during" the execution of a user specified
+	 * probe handler, invoke just that probe's fault handler
+	 */
+	if (curr_kprobe && curr_kprobe->fault_handler) {
+		if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Fill in the required fields of the "manager kprobe". Replace the
+ * earlier kprobe in the hlist with the manager kprobe
+ */
+static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
+{
+	ap->addr = p->addr;
+	ap->opcode = p->opcode;
+	memcpy(&ap->ainsn, &p->ainsn, sizeof(struct arch_specific_insn));
+
+	ap->pre_handler = aggr_pre_handler;
+	ap->post_handler = aggr_post_handler;
+	ap->fault_handler = aggr_fault_handler;
+
+	INIT_LIST_HEAD(&ap->list);
+	list_add(&p->list, &ap->list);
+
+	INIT_HLIST_NODE(&ap->hlist);
+	hlist_del(&p->hlist);
+	hlist_add_head(&ap->hlist,
+		&kprobe_table[hash_ptr(ap->addr, KPROBE_HASH_BITS)]);
+}
+
+/*
+ * This is the second or subsequent kprobe at the address - handle
+ * the intricacies
+ * TODO: Move kcalloc outside the spinlock
+ */
+static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+	int ret = 0;
+	struct kprobe *ap;
+
+	if (old_p->break_handler || p->break_handler) {
+		ret = -EEXIST;	/* kprobe and jprobe can't (yet) coexist */
+	} else if (old_p->pre_handler == aggr_pre_handler) {
+		list_add(&p->list, &old_p->list);
+	} else {
+		ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
+		if (!ap)
+			return -ENOMEM;
+		add_aggr_kprobe(ap, old_p);
+		list_add(&p->list, &ap->list);
+	}
+	return ret;
+}
+
+/* kprobe removal house-keeping routines */
+static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
+{
+	*p->addr = p->opcode;
+	hlist_del(&p->hlist);
+	flush_icache_range((unsigned long) p->addr,
+		   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+	spin_unlock_irqrestore(&kprobe_lock, flags);
+	arch_remove_kprobe(p);
+}
+
+static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
+		struct kprobe *p, unsigned long flags)
+{
+	list_del(&p->list);
+	if (list_empty(&old_p->list)) {
+		cleanup_kprobe(old_p, flags);
+		kfree(old_p);
+	} else
+		spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
 int register_kprobe(struct kprobe *p)
 {
 	int ret = 0;
 	unsigned long flags = 0;
+	struct kprobe *old_p;
 
 	if ((ret = arch_prepare_kprobe(p)) != 0) {
 		goto rm_kprobe;
 	}
 	spin_lock_irqsave(&kprobe_lock, flags);
-	INIT_HLIST_NODE(&p->hlist);
-	if (get_kprobe(p->addr)) {
-		ret = -EEXIST;
+	old_p = get_kprobe(p->addr);
+	if (old_p) {
+		ret = register_aggr_kprobe(old_p, p);
 		goto out;
 	}
-	arch_copy_kprobe(p);
 
+	arch_copy_kprobe(p);
+	INIT_HLIST_NODE(&p->hlist);
 	hlist_add_head(&p->hlist,
 		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
 
@@ -107,13 +225,17 @@
 void unregister_kprobe(struct kprobe *p)
 {
 	unsigned long flags;
-	arch_remove_kprobe(p);
+	struct kprobe *old_p;
+
 	spin_lock_irqsave(&kprobe_lock, flags);
-	*p->addr = p->opcode;
-	hlist_del(&p->hlist);
-	flush_icache_range((unsigned long) p->addr,
-			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
-	spin_unlock_irqrestore(&kprobe_lock, flags);
+	old_p = get_kprobe(p->addr);
+	if (old_p) {
+		if (old_p->pre_handler == aggr_pre_handler)
+			cleanup_aggr_kprobe(old_p, p, flags);
+		else
+			cleanup_kprobe(p, flags);
+	} else
+		spin_unlock_irqrestore(&kprobe_lock, flags);
 }
 
 static struct notifier_block kprobe_exceptions_nb = {
diff --git a/kernel/kthread.c b/kernel/kthread.c
index e377e22..f50f174 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -174,7 +174,7 @@
 
 	/* Must init completion *before* thread sees kthread_stop_info.k */
 	init_completion(&kthread_stop_info.done);
-	wmb();
+	smp_wmb();
 
 	/* Now set kthread_should_stop() to true, and wake it up. */
 	kthread_stop_info.k = k;
diff --git a/kernel/module.c b/kernel/module.c
index 2dbfa07..5734ab0 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1801,7 +1801,7 @@
 		/* Init routine failed: abort.  Try to protect us from
                    buggy refcounters. */
 		mod->state = MODULE_STATE_GOING;
-		synchronize_kernel();
+		synchronize_sched();
 		if (mod->unsafe)
 			printk(KERN_ERR "%s: module is now stuck!\n",
 			       mod->name);
diff --git a/kernel/panic.c b/kernel/panic.c
index 0fa3f3a..081f746 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -102,9 +102,9 @@
 #ifdef __sparc__
 	{
 		extern int stop_a_enabled;
-		/* Make sure the user can actually press L1-A */
+		/* Make sure the user can actually press Stop-A (L1-A) */
 		stop_a_enabled = 1;
-		printk(KERN_EMERG "Press L1-A to return to the boot prom\n");
+		printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n");
 	}
 #endif
 #if defined(CONFIG_ARCH_S390)
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index ae5bebc..90b3b68 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -1099,7 +1099,7 @@
 	return pblist;
 }
 
-/**
+/*
  *	Using bio to read from swap.
  *	This code requires a bit more work than just using buffer heads
  *	but, it is the recommended way for 2.5/2.6.
diff --git a/kernel/printk.c b/kernel/printk.c
index 1498689..290a07c 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -85,10 +85,6 @@
  */
 static DEFINE_SPINLOCK(logbuf_lock);
 
-static char __log_buf[__LOG_BUF_LEN];
-static char *log_buf = __log_buf;
-static int log_buf_len = __LOG_BUF_LEN;
-
 #define LOG_BUF_MASK	(log_buf_len-1)
 #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
 
@@ -99,7 +95,6 @@
 static unsigned long log_start;	/* Index into log_buf: next char to be read by syslog() */
 static unsigned long con_start;	/* Index into log_buf: next char to be sent to consoles */
 static unsigned long log_end;	/* Index into log_buf: most-recently-written-char + 1 */
-static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
 
 /*
  *	Array of consoles built from command line options (console=)
@@ -120,6 +115,13 @@
 /* Flag: console code may call schedule() */
 static int console_may_schedule;
 
+#ifdef CONFIG_PRINTK
+
+static char __log_buf[__LOG_BUF_LEN];
+static char *log_buf = __log_buf;
+static int log_buf_len = __LOG_BUF_LEN;
+static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
+
 /*
  *	Setup a list of consoles. Called from init/main.c
  */
@@ -535,6 +537,7 @@
  * then changes console_loglevel may break. This is because console_loglevel
  * is inspected when the actual printing occurs.
  */
+
 asmlinkage int printk(const char *fmt, ...)
 {
 	va_list args;
@@ -655,6 +658,18 @@
 EXPORT_SYMBOL(printk);
 EXPORT_SYMBOL(vprintk);
 
+#else
+
+asmlinkage long sys_syslog(int type, char __user * buf, int len)
+{
+	return 0;
+}
+
+int do_syslog(int type, char __user * buf, int len) { return 0; }
+static void call_console_drivers(unsigned long start, unsigned long end) {}
+
+#endif
+
 /**
  * acquire_console_sem - lock the console system for exclusive use.
  *
@@ -931,7 +946,7 @@
 	return res;
 }
 EXPORT_SYMBOL(unregister_console);
-	
+
 /**
  * tty_write_message - write a message to a certain tty, not just the console.
  *
diff --git a/kernel/profile.c b/kernel/profile.c
index a38fa70..0221a50 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -184,7 +184,7 @@
 	WARN_ON(hook != timer_hook);
 	timer_hook = NULL;
 	/* make sure all CPUs see the NULL hook */
-	synchronize_kernel();
+	synchronize_sched();  /* Allow ongoing interrupts to complete. */
 }
 
 EXPORT_SYMBOL_GPL(register_timer_hook);
@@ -522,7 +522,7 @@
 	return 0;
 out_cleanup:
 	prof_on = 0;
-	mb();
+	smp_mb();
 	on_each_cpu(profile_nop, NULL, 0, 1);
 	for_each_online_cpu(cpu) {
 		struct page *page;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 88b306c..8dcb8f6 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -16,6 +16,7 @@
 #include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -135,7 +136,7 @@
  	    (current->gid != task->sgid) ||
  	    (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
 		goto bad;
-	rmb();
+	smp_rmb();
 	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
 		goto bad;
 	/* the same process cannot be attached many times */
@@ -166,7 +167,7 @@
 
 int ptrace_detach(struct task_struct *child, unsigned int data)
 {
-	if ((unsigned long) data > _NSIG)
+	if (!valid_signal(data))
 		return	-EIO;
 
 	/* Architecture-specific hardware disable .. */
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index d00eded..f436993 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -444,15 +444,18 @@
 }
 
 /**
- * synchronize_kernel - wait until a grace period has elapsed.
+ * synchronize_rcu - wait until a grace period has elapsed.
  *
  * Control will return to the caller some time after a full grace
  * period has elapsed, in other words after all currently executing RCU
  * read-side critical sections have completed.  RCU read-side critical
  * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
  * and may be nested.
+ *
+ * If your read-side code is not protected by rcu_read_lock(), do -not-
+ * use synchronize_rcu().
  */
-void synchronize_kernel(void)
+void synchronize_rcu(void)
 {
 	struct rcu_synchronize rcu;
 
@@ -464,7 +467,16 @@
 	wait_for_completion(&rcu.completion);
 }
 
+/*
+ * Deprecated, use synchronize_rcu() or synchronize_sched() instead.
+ */
+void synchronize_kernel(void)
+{
+	synchronize_rcu();
+}
+
 module_param(maxbatch, int, 0);
-EXPORT_SYMBOL_GPL(call_rcu);
-EXPORT_SYMBOL_GPL(call_rcu_bh);
-EXPORT_SYMBOL_GPL(synchronize_kernel);
+EXPORT_SYMBOL(call_rcu);  /* WARNING: GPL-only in April 2006. */
+EXPORT_SYMBOL(call_rcu_bh);  /* WARNING: GPL-only in April 2006. */
+EXPORT_SYMBOL_GPL(synchronize_rcu);
+EXPORT_SYMBOL(synchronize_kernel);  /* WARNING: GPL-only in April 2006. */
diff --git a/kernel/sched.c b/kernel/sched.c
index 9bb7489..0dc3158 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2906,6 +2906,7 @@
  * @q: the waitqueue
  * @mode: which threads
  * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ * @key: is directly passed to the wakeup function
  */
 void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
 				int nr_exclusive, void *key)
@@ -2928,7 +2929,7 @@
 }
 
 /**
- * __wake_up - sync- wake up threads blocked on a waitqueue.
+ * __wake_up_sync - wake up threads blocked on a waitqueue.
  * @q: the waitqueue
  * @mode: which threads
  * @nr_exclusive: how many wake-one or wake-many threads to wake up
@@ -3223,6 +3224,19 @@
 
 EXPORT_SYMBOL(set_user_nice);
 
+/*
+ * can_nice - check if a task can reduce its nice value
+ * @p: task
+ * @nice: nice value
+ */
+int can_nice(const task_t *p, const int nice)
+{
+	/* convert nice value [19,-20] to rlimit style value [0,39] */
+	int nice_rlim = 19 - nice;
+	return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur ||
+		capable(CAP_SYS_NICE));
+}
+
 #ifdef __ARCH_WANT_SYS_NICE
 
 /*
@@ -3242,12 +3256,8 @@
 	 * We don't have to worry. Conceptually one call occurs first
 	 * and we have a single winner.
 	 */
-	if (increment < 0) {
-		if (!capable(CAP_SYS_NICE))
-			return -EPERM;
-		if (increment < -40)
-			increment = -40;
-	}
+	if (increment < -40)
+		increment = -40;
 	if (increment > 40)
 		increment = 40;
 
@@ -3257,6 +3267,9 @@
 	if (nice > 19)
 		nice = 19;
 
+	if (increment < 0 && !can_nice(current, nice))
+		return -EPERM;
+
 	retval = security_task_setnice(current, nice);
 	if (retval)
 		return retval;
@@ -3372,6 +3385,7 @@
 		return -EINVAL;
 
 	if ((policy == SCHED_FIFO || policy == SCHED_RR) &&
+	    param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur &&
 	    !capable(CAP_SYS_NICE))
 		return -EPERM;
 	if ((current->euid != p->euid) && (current->euid != p->uid) &&
diff --git a/kernel/signal.c b/kernel/signal.c
index e6567d7..8f3debc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -23,6 +23,7 @@
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
 #include <linux/posix-timers.h>
+#include <linux/signal.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -646,7 +647,7 @@
 				 struct task_struct *t)
 {
 	int error = -EINVAL;
-	if (sig < 0 || sig > _NSIG)
+	if (!valid_signal(sig))
 		return error;
 	error = -EPERM;
 	if ((!info || ((unsigned long)info != 1 &&
@@ -1245,7 +1246,7 @@
 	 * Make sure legacy kernel users don't send in bad values
 	 * (normal paths check this in check_kill_permission).
 	 */
-	if (sig < 0 || sig > _NSIG)
+	if (!valid_signal(sig))
 		return -EINVAL;
 
 	/*
@@ -1520,7 +1521,7 @@
 		if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
 			sig = 0;
 	}
-	if (sig > 0 && sig <= _NSIG)
+	if (valid_signal(sig) && sig > 0)
 		__group_send_sig_info(sig, &info, tsk->parent);
 	__wake_up_parent(tsk, tsk->parent);
 	spin_unlock_irqrestore(&psig->siglock, flags);
@@ -2364,7 +2365,7 @@
 {
 	struct k_sigaction *k;
 
-	if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig)))
+	if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
 		return -EINVAL;
 
 	k = &current->sighand->action[sig-1];
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index c39ed70..6116b25 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -33,7 +33,7 @@
 	set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
 
 	/* Ack: we are alive */
-	mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
+	smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
 	atomic_inc(&stopmachine_thread_ack);
 
 	/* Simple state machine */
@@ -43,14 +43,14 @@
 			local_irq_disable();
 			irqs_disabled = 1;
 			/* Ack: irqs disabled. */
-			mb(); /* Must read state first. */
+			smp_mb(); /* Must read state first. */
 			atomic_inc(&stopmachine_thread_ack);
 		} else if (stopmachine_state == STOPMACHINE_PREPARE
 			   && !prepared) {
 			/* Everyone is in place, hold CPU. */
 			preempt_disable();
 			prepared = 1;
-			mb(); /* Must read state first. */
+			smp_mb(); /* Must read state first. */
 			atomic_inc(&stopmachine_thread_ack);
 		}
 		/* Yield in first stage: migration threads need to
@@ -62,7 +62,7 @@
 	}
 
 	/* Ack: we are exiting. */
-	mb(); /* Must read state first. */
+	smp_mb(); /* Must read state first. */
 	atomic_inc(&stopmachine_thread_ack);
 
 	if (irqs_disabled)
@@ -77,7 +77,7 @@
 static void stopmachine_set_state(enum stopmachine_state state)
 {
 	atomic_set(&stopmachine_thread_ack, 0);
-	wmb();
+	smp_wmb();
 	stopmachine_state = state;
 	while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads)
 		cpu_relax();
diff --git a/kernel/sys.c b/kernel/sys.c
index 462d78d..f006632 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -25,6 +25,7 @@
 #include <linux/dcookies.h>
 #include <linux/suspend.h>
 #include <linux/tty.h>
+#include <linux/signal.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
@@ -227,7 +228,7 @@
 		error = -EPERM;
 		goto out;
 	}
-	if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) {
+	if (niceval < task_nice(p) && !can_nice(p, niceval)) {
 		error = -EACCES;
 		goto out;
 	}
@@ -525,7 +526,7 @@
 	if (new_egid != old_egid)
 	{
 		current->mm->dumpable = 0;
-		wmb();
+		smp_wmb();
 	}
 	if (rgid != (gid_t) -1 ||
 	    (egid != (gid_t) -1 && egid != old_rgid))
@@ -556,7 +557,7 @@
 		if(old_egid != gid)
 		{
 			current->mm->dumpable=0;
-			wmb();
+			smp_wmb();
 		}
 		current->gid = current->egid = current->sgid = current->fsgid = gid;
 	}
@@ -565,7 +566,7 @@
 		if(old_egid != gid)
 		{
 			current->mm->dumpable=0;
-			wmb();
+			smp_wmb();
 		}
 		current->egid = current->fsgid = gid;
 	}
@@ -596,7 +597,7 @@
 	if(dumpclear)
 	{
 		current->mm->dumpable = 0;
-		wmb();
+		smp_wmb();
 	}
 	current->uid = new_ruid;
 	return 0;
@@ -653,7 +654,7 @@
 	if (new_euid != old_euid)
 	{
 		current->mm->dumpable=0;
-		wmb();
+		smp_wmb();
 	}
 	current->fsuid = current->euid = new_euid;
 	if (ruid != (uid_t) -1 ||
@@ -703,7 +704,7 @@
 	if (old_euid != uid)
 	{
 		current->mm->dumpable = 0;
-		wmb();
+		smp_wmb();
 	}
 	current->fsuid = current->euid = uid;
 	current->suid = new_suid;
@@ -748,7 +749,7 @@
 		if (euid != current->euid)
 		{
 			current->mm->dumpable = 0;
-			wmb();
+			smp_wmb();
 		}
 		current->euid = euid;
 	}
@@ -798,7 +799,7 @@
 		if (egid != current->egid)
 		{
 			current->mm->dumpable = 0;
-			wmb();
+			smp_wmb();
 		}
 		current->egid = egid;
 	}
@@ -845,7 +846,7 @@
 		if (uid != old_fsuid)
 		{
 			current->mm->dumpable = 0;
-			wmb();
+			smp_wmb();
 		}
 		current->fsuid = uid;
 	}
@@ -875,7 +876,7 @@
 		if (gid != old_fsgid)
 		{
 			current->mm->dumpable = 0;
-			wmb();
+			smp_wmb();
 		}
 		current->fsgid = gid;
 		key_fsgid_changed(current);
@@ -1194,7 +1195,7 @@
 	return 0;
 }
 
-/* a simple shell-metzner sort */
+/* a simple Shell sort */
 static void groups_sort(struct group_info *group_info)
 {
 	int base, max, stride;
@@ -1637,7 +1638,7 @@
 	switch (option) {
 		case PR_SET_PDEATHSIG:
 			sig = arg2;
-			if (sig < 0 || sig > _NSIG) {
+			if (!valid_signal(sig)) {
 				error = -EINVAL;
 				break;
 			}
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 1802a31..0dda70e 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -52,6 +52,7 @@
 cond_syscall(sys_msgrcv);
 cond_syscall(sys_msgctl);
 cond_syscall(sys_shmget);
+cond_syscall(sys_shmat);
 cond_syscall(sys_shmdt);
 cond_syscall(sys_shmctl);
 cond_syscall(sys_mq_open);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 79dbd93..701d12c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1991,6 +1991,8 @@
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
+ * @ppos: the current position in the file
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
diff --git a/kernel/time.c b/kernel/time.c
index 96fd0f4..d4335c1 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -516,14 +516,6 @@
 
 	write_seqlock_irq(&xtime_lock);
 	{
-		/*
-		 * This is revolting. We need to set "xtime" correctly. However, the value
-		 * in this location is the value at the most recent update of wall time.
-		 * Discover what correction gettimeofday would have done, and then undo
-		 * it!
-		 */
-		nsec -= time_interpolator_get_offset();
-
 		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
 		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
 
diff --git a/kernel/timer.c b/kernel/timer.c
index ecb3d67..207aa4f0 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1007,7 +1007,7 @@
 		 * Make sure we read the pid before re-reading the
 		 * parent pointer:
 		 */
-		rmb();
+		smp_rmb();
 		parent = me->group_leader->real_parent;
 		if (old != parent)
 			continue;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 426a0cf..ac23847 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -108,6 +108,7 @@
 
 config DEBUG_BUGVERBOSE
 	bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
+	depends on BUG
 	depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64) || FRV
 	default !EMBEDDED
 	help
diff --git a/lib/kobject.c b/lib/kobject.c
index 5df8441..9404882 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -216,13 +216,12 @@
 /**
  *	kobject_set_name - Set the name of an object
  *	@kobj:	object.
- *	@name:	name. 
+ *	@fmt:	format string used to build the name
  *
  *	If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
  *	string that @kobj->k_name points to. Otherwise, use the static 
  *	@kobj->name array.
  */
-
 int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
 {
 	int error = 0;
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
index 21f0db2..40ffde9 100644
--- a/lib/rwsem-spinlock.c
+++ b/lib/rwsem-spinlock.c
@@ -76,7 +76,7 @@
 		list_del(&waiter->list);
 		tsk = waiter->task;
 		/* Don't touch waiter after ->task has been NULLed */
-		mb();
+		smp_mb();
 		waiter->task = NULL;
 		wake_up_process(tsk);
 		put_task_struct(tsk);
@@ -91,7 +91,7 @@
 
 		list_del(&waiter->list);
 		tsk = waiter->task;
-		mb();
+		smp_mb();
 		waiter->task = NULL;
 		wake_up_process(tsk);
 		put_task_struct(tsk);
@@ -123,7 +123,7 @@
 	list_del(&waiter->list);
 
 	tsk = waiter->task;
-	mb();
+	smp_mb();
 	waiter->task = NULL;
 	wake_up_process(tsk);
 	put_task_struct(tsk);
diff --git a/lib/rwsem.c b/lib/rwsem.c
index 7644089..62fa4eb 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -74,7 +74,7 @@
 	 */
 	list_del(&waiter->list);
 	tsk = waiter->task;
-	mb();
+	smp_mb();
 	waiter->task = NULL;
 	wake_up_process(tsk);
 	put_task_struct(tsk);
@@ -117,7 +117,7 @@
 		waiter = list_entry(next, struct rwsem_waiter, list);
 		next = waiter->list.next;
 		tsk = waiter->task;
-		mb();
+		smp_mb();
 		waiter->task = NULL;
 		wake_up_process(tsk);
 		put_task_struct(tsk);
diff --git a/lib/sort.c b/lib/sort.c
index ea3caed..b73dbb0 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -90,7 +90,7 @@
 
 static int sort_test(void)
 {
-	int *a, i, r = 0;
+	int *a, i, r = 1;
 
 	a = kmalloc(1000 * sizeof(int), GFP_KERNEL);
 	BUG_ON(!a);
diff --git a/lib/string.c b/lib/string.c
index 4bb93ad..d886ef1 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -65,6 +65,7 @@
  * @dest: Where to copy the string to
  * @src: Where to copy the string from
  */
+#undef strcpy
 char * strcpy(char * dest,const char *src)
 {
 	char *tmp = dest;
@@ -85,6 +86,10 @@
  *
  * The result is not %NUL-terminated if the source exceeds
  * @count bytes.
+ *
+ * In the case where the length of @src is less than  that  of
+ * count, the remainder of @dest will be padded with %NUL.
+ *
  */
 char * strncpy(char * dest,const char *src,size_t count)
 {
@@ -132,6 +137,7 @@
  * @dest: The string to be appended to
  * @src: The string to append to it
  */
+#undef strcat
 char * strcat(char * dest, const char * src)
 {
 	char *tmp = dest;
@@ -209,6 +215,7 @@
  * @cs: One string
  * @ct: Another string
  */
+#undef strcmp
 int strcmp(const char * cs,const char * ct)
 {
 	register signed char __res;
@@ -514,6 +521,7 @@
  * @ct: Another area of memory
  * @count: The size of the area.
  */
+#undef memcmp
 int memcmp(const void * cs,const void * ct,size_t count)
 {
 	const unsigned char *su1, *su2;
diff --git a/mm/filemap.c b/mm/filemap.c
index 93595c3..47263ac 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -29,11 +29,6 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 /*
- * This is needed for the following functions:
- *  - try_to_release_page
- *  - block_invalidatepage
- *  - generic_osync_inode
- *
  * FIXME: remove all knowledge of the buffer layer from the core VM
  */
 #include <linux/buffer_head.h> /* for generic_osync_inode */
@@ -123,8 +118,7 @@
 {
 	struct address_space *mapping = page->mapping;
 
-	if (unlikely(!PageLocked(page)))
-		PAGE_BUG(page);
+	BUG_ON(!PageLocked(page));
 
 	write_lock_irq(&mapping->tree_lock);
 	__remove_from_page_cache(page);
@@ -139,7 +133,25 @@
 	page = container_of((page_flags_t *)word, struct page, flags);
 
 	/*
-	 * FIXME, fercrissake.  What is this barrier here for?
+	 * page_mapping() is being called without PG_locked held.
+	 * Some knowledge of the state and use of the page is used to
+	 * reduce the requirements down to a memory barrier.
+	 * The danger here is of a stale page_mapping() return value
+	 * indicating a struct address_space different from the one it's
+	 * associated with when it is associated with one.
+	 * After smp_mb(), it's either the correct page_mapping() for
+	 * the page, or an old page_mapping() and the page's own
+	 * page_mapping() has gone NULL.
+	 * The ->sync_page() address_space operation must tolerate
+	 * page_mapping() going NULL. By an amazing coincidence,
+	 * this comes about because none of the users of the page
+	 * in the ->sync_page() methods make essential use of the
+	 * page_mapping(), merely passing the page down to the backing
+	 * device's unplug functions when it's non-NULL, which in turn
+	 * ignore it for all cases but swap, where only page->private is
+	 * of interest. When page_mapping() does go NULL, the entire
+	 * call stack gracefully ignores the page and returns.
+	 * -- wli
 	 */
 	smp_mb();
 	mapping = page_mapping(page);
@@ -152,9 +164,10 @@
 /**
  * filemap_fdatawrite_range - start writeback against all of a mapping's
  * dirty pages that lie within the byte offsets <start, end>
- * @mapping: address space structure to write
- * @start: offset in bytes where the range starts
- * @end : offset in bytes where the range ends
+ * @mapping:	address space structure to write
+ * @start:	offset in bytes where the range starts
+ * @end:	offset in bytes where the range ends
+ * @sync_mode:	enable synchronous operation
  *
  * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as
  * opposed to a regular memory * cleansing writeback.  The difference between
@@ -518,8 +531,8 @@
 /**
  * find_lock_page - locate, pin and lock a pagecache page
  *
- * @mapping - the address_space to search
- * @offset - the page index
+ * @mapping: the address_space to search
+ * @offset: the page index
  *
  * Locates the desired pagecache page, locks it, increments its reference
  * count and returns its address.
@@ -558,9 +571,9 @@
 /**
  * find_or_create_page - locate or add a pagecache page
  *
- * @mapping - the page's address_space
- * @index - the page's index into the mapping
- * @gfp_mask - page allocation mode
+ * @mapping: the page's address_space
+ * @index: the page's index into the mapping
+ * @gfp_mask: page allocation mode
  *
  * Locates a page in the pagecache.  If the page is not present, a new page
  * is allocated using @gfp_mask and is added to the pagecache and to the VM's
@@ -1949,7 +1962,7 @@
 		buf = iov->iov_base + written;
 	else {
 		filemap_set_next_iovec(&cur_iov, &iov_base, written);
-		buf = iov->iov_base + iov_base;
+		buf = cur_iov->iov_base + iov_base;
 	}
 
 	do {
@@ -2007,9 +2020,11 @@
 				count -= status;
 				pos += status;
 				buf += status;
-				if (unlikely(nr_segs > 1))
+				if (unlikely(nr_segs > 1)) {
 					filemap_set_next_iovec(&cur_iov,
 							&iov_base, status);
+					buf = cur_iov->iov_base + iov_base;
+				}
 			}
 		}
 		if (unlikely(copied != bytes))
diff --git a/mm/highmem.c b/mm/highmem.c
index d012765..4009115 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -325,6 +325,7 @@
 			continue;
 
 		mempool_free(bvec->bv_page, pool);	
+		dec_page_state(nr_bounce);
 	}
 
 	bio_endio(bio_orig, bio_orig->bi_size, err);
@@ -405,6 +406,7 @@
 		to->bv_page = mempool_alloc(pool, q->bounce_gfp);
 		to->bv_len = from->bv_len;
 		to->bv_offset = from->bv_offset;
+		inc_page_state(nr_bounce);
 
 		if (rw == WRITE) {
 			char *vto, *vfrom;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index a3b44a6..08c41da 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -661,7 +661,7 @@
 	case MPOL_BIND:
 		/* Lower zones don't get a policy applied */
 		/* Careful: current->mems_allowed might have moved */
-		if (gfp >= policy_zone)
+		if ((gfp & GFP_ZONEMASK) >= policy_zone)
 			if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
 				return policy->v.zonelist;
 		/*FALL THROUGH*/
diff --git a/mm/mempool.c b/mm/mempool.c
index b014ffe..c9f3d46 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -198,31 +198,22 @@
 	void *element;
 	unsigned long flags;
 	DEFINE_WAIT(wait);
-	int gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
+	int gfp_temp;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
+
+	gfp_mask |= __GFP_NOMEMALLOC;	/* don't allocate emergency reserves */
+	gfp_mask |= __GFP_NORETRY;	/* don't loop in __alloc_pages */
+	gfp_mask |= __GFP_NOWARN;	/* failures are OK */
+
+	gfp_temp = gfp_mask & ~(__GFP_WAIT|__GFP_IO);
+
 repeat_alloc:
-	element = pool->alloc(gfp_nowait|__GFP_NOWARN, pool->pool_data);
+
+	element = pool->alloc(gfp_temp, pool->pool_data);
 	if (likely(element != NULL))
 		return element;
 
-	/*
-	 * If the pool is less than 50% full and we can perform effective
-	 * page reclaim then try harder to allocate an element.
-	 */
-	mb();
-	if ((gfp_mask & __GFP_FS) && (gfp_mask != gfp_nowait) &&
-				(pool->curr_nr <= pool->min_nr/2)) {
-		element = pool->alloc(gfp_mask, pool->pool_data);
-		if (likely(element != NULL))
-			return element;
-	}
-
-	/*
-	 * Kick the VM at this point.
-	 */
-	wakeup_bdflush(0);
-
 	spin_lock_irqsave(&pool->lock, flags);
 	if (likely(pool->curr_nr)) {
 		element = remove_element(pool);
@@ -235,8 +226,10 @@
 	if (!(gfp_mask & __GFP_WAIT))
 		return NULL;
 
+	/* Now start performing page reclaim */
+	gfp_temp = gfp_mask;
 	prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
-	mb();
+	smp_mb();
 	if (!pool->curr_nr)
 		io_schedule();
 	finish_wait(&pool->wait, &wait);
@@ -257,7 +250,7 @@
 {
 	unsigned long flags;
 
-	mb();
+	smp_mb();
 	if (pool->curr_nr < pool->min_nr) {
 		spin_lock_irqsave(&pool->lock, flags);
 		if (pool->curr_nr < pool->min_nr) {
diff --git a/mm/mmap.c b/mm/mmap.c
index 6ea204c..01f9793 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -937,9 +937,10 @@
 	/* mlock MCL_FUTURE? */
 	if (vm_flags & VM_LOCKED) {
 		unsigned long locked, lock_limit;
-		locked = mm->locked_vm << PAGE_SHIFT;
+		locked = len >> PAGE_SHIFT;
+		locked += mm->locked_vm;
 		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
-		locked += len;
+		lock_limit >>= PAGE_SHIFT;
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
 	}
@@ -1009,8 +1010,7 @@
 	}
 
 	/* Check against address space limit. */
-	if ((mm->total_vm << PAGE_SHIFT) + len
-	    > current->signal->rlim[RLIMIT_AS].rlim_cur)
+	if (!may_expand_vm(mm, len >> PAGE_SHIFT))
 		return -ENOMEM;
 
 	if (accountable && (!(flags & MAP_NORESERVE) ||
@@ -1421,7 +1421,7 @@
 	struct rlimit *rlim = current->signal->rlim;
 
 	/* address space limit tests */
-	if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
+	if (!may_expand_vm(mm, grow))
 		return -ENOMEM;
 
 	/* Stack limit test */
@@ -1823,9 +1823,10 @@
 	 */
 	if (mm->def_flags & VM_LOCKED) {
 		unsigned long locked, lock_limit;
-		locked = mm->locked_vm << PAGE_SHIFT;
+		locked = len >> PAGE_SHIFT;
+		locked += mm->locked_vm;
 		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
-		locked += len;
+		lock_limit >>= PAGE_SHIFT;
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
 	}
@@ -1848,8 +1849,7 @@
 	}
 
 	/* Check against address space limits *after* clearing old maps... */
-	if ((mm->total_vm << PAGE_SHIFT) + len
-	    > current->signal->rlim[RLIMIT_AS].rlim_cur)
+	if (!may_expand_vm(mm, len >> PAGE_SHIFT))
 		return -ENOMEM;
 
 	if (mm->map_count > sysctl_max_map_count)
@@ -2019,3 +2019,19 @@
 	}
 	return new_vma;
 }
+
+/*
+ * Return true if the calling process may expand its vm space by the passed
+ * number of pages
+ */
+int may_expand_vm(struct mm_struct *mm, unsigned long npages)
+{
+	unsigned long cur = mm->total_vm;	/* pages */
+	unsigned long lim;
+
+	lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+
+	if (cur + npages > lim)
+		return 0;
+	return 1;
+}
diff --git a/mm/mremap.c b/mm/mremap.c
index 0d1c1b9..0dd7ace 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -347,10 +347,10 @@
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			goto out;
 	}
-	ret = -ENOMEM;
-	if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
-	    > current->signal->rlim[RLIMIT_AS].rlim_cur)
+	if (!may_expand_vm(current->mm, (new_len - old_len) >> PAGE_SHIFT)) {
+		ret = -ENOMEM;
 		goto out;
+	}
 
 	if (vma->vm_flags & VM_ACCOUNT) {
 		charged = (new_len - old_len) >> PAGE_SHIFT;
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 6ddd6a2..613b99a 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -255,7 +255,7 @@
 
 /**
  * balance_dirty_pages_ratelimited - balance dirty memory state
- * @mapping - address_space which was dirtied
+ * @mapping: address_space which was dirtied
  *
  * Processes which are dirtying memory should call in here once for each page
  * which was newly dirtied.  The function will periodically check the system's
@@ -562,8 +562,8 @@
 /**
  * write_one_page - write out a single page and optionally wait on I/O
  *
- * @page - the page to write
- * @wait - if true, wait on writeout
+ * @page: the page to write
+ * @wait: if true, wait on writeout
  *
  * The page must be locked by the caller and will be unlocked upon return.
  *
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c73dbbc..b1061b1 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -43,7 +43,9 @@
  * initializer cleaner
  */
 nodemask_t node_online_map = { { [0] = 1UL } };
+EXPORT_SYMBOL(node_online_map);
 nodemask_t node_possible_map = NODE_MASK_ALL;
+EXPORT_SYMBOL(node_possible_map);
 struct pglist_data *pgdat_list;
 unsigned long totalram_pages;
 unsigned long totalhigh_pages;
@@ -799,14 +801,18 @@
 	}
 
 	/* This allocation should allow future memory freeing. */
-	if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) && !in_interrupt()) {
-		/* go through the zonelist yet again, ignoring mins */
-		for (i = 0; (z = zones[i]) != NULL; i++) {
-			if (!cpuset_zone_allowed(z))
-				continue;
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page)
-				goto got_pg;
+
+	if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE)))
+			&& !in_interrupt()) {
+		if (!(gfp_mask & __GFP_NOMEMALLOC)) {
+			/* go through the zonelist yet again, ignoring mins */
+			for (i = 0; (z = zones[i]) != NULL; i++) {
+				if (!cpuset_zone_allowed(z))
+					continue;
+				page = buffered_rmqueue(z, order, gfp_mask);
+				if (page)
+					goto got_pg;
+			}
 		}
 		goto nopage;
 	}
@@ -1351,8 +1357,7 @@
 #define MAX_NODE_LOAD (num_online_nodes())
 static int __initdata node_load[MAX_NUMNODES];
 /**
- * find_next_best_node - find the next node that should appear in a given
- *    node's fallback list
+ * find_next_best_node - find the next node that should appear in a given node's fallback list
  * @node: node whose fallback list we're appending
  * @used_node_mask: nodemask_t of already used nodes
  *
@@ -1671,6 +1676,18 @@
 		if (batch < 1)
 			batch = 1;
 
+		/*
+		 * Clamp the batch to a 2^n - 1 value. Having a power
+		 * of 2 value was found to be more likely to have
+		 * suboptimal cache aliasing properties in some cases.
+		 *
+		 * For example if 2 tasks are alternately allocating
+		 * batches of pages, one task can end up with a lot
+		 * of pages of one half of the possible page colors
+		 * and the other with pages of the other colors.
+		 */
+		batch = (1 << fls(batch + batch/2)) - 1;
+
 		for (cpu = 0; cpu < NR_CPUS; cpu++) {
 			struct per_cpu_pages *pcp;
 
@@ -1881,6 +1898,7 @@
 	"allocstall",
 
 	"pgrotated",
+	"nr_bounce",
 };
 
 static void *vmstat_start(struct seq_file *m, loff_t *pos)
diff --git a/mm/rmap.c b/mm/rmap.c
index 884d6d1..378de23 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -243,6 +243,42 @@
 }
 
 /*
+ * Check that @page is mapped at @address into @mm.
+ *
+ * On success returns with mapped pte and locked mm->page_table_lock.
+ */
+static pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+					unsigned long address)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	/*
+	 * We need the page_table_lock to protect us from page faults,
+	 * munmap, fork, etc...
+	 */
+	spin_lock(&mm->page_table_lock);
+	pgd = pgd_offset(mm, address);
+	if (likely(pgd_present(*pgd))) {
+		pud = pud_offset(pgd, address);
+		if (likely(pud_present(*pud))) {
+			pmd = pmd_offset(pud, address);
+			if (likely(pmd_present(*pmd))) {
+				pte = pte_offset_map(pmd, address);
+				if (likely(pte_present(*pte) &&
+					   page_to_pfn(page) == pte_pfn(*pte)))
+					return pte;
+				pte_unmap(pte);
+			}
+		}
+	}
+	spin_unlock(&mm->page_table_lock);
+	return ERR_PTR(-ENOENT);
+}
+
+/*
  * Subfunctions of page_referenced: page_referenced_one called
  * repeatedly from either page_referenced_anon or page_referenced_file.
  */
@@ -251,9 +287,6 @@
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
 	pte_t *pte;
 	int referenced = 0;
 
@@ -263,39 +296,18 @@
 	if (address == -EFAULT)
 		goto out;
 
-	spin_lock(&mm->page_table_lock);
+	pte = page_check_address(page, mm, address);
+	if (!IS_ERR(pte)) {
+		if (ptep_clear_flush_young(vma, address, pte))
+			referenced++;
 
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
-		goto out_unlock;
+		if (mm != current->mm && !ignore_token && has_swap_token(mm))
+			referenced++;
 
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
-		goto out_unlock;
-
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
-		goto out_unlock;
-
-	pte = pte_offset_map(pmd, address);
-	if (!pte_present(*pte))
-		goto out_unmap;
-
-	if (page_to_pfn(page) != pte_pfn(*pte))
-		goto out_unmap;
-
-	if (ptep_clear_flush_young(vma, address, pte))
-		referenced++;
-
-	if (mm != current->mm && !ignore_token && has_swap_token(mm))
-		referenced++;
-
-	(*mapcount)--;
-
-out_unmap:
-	pte_unmap(pte);
-out_unlock:
-	spin_unlock(&mm->page_table_lock);
+		(*mapcount)--;
+		pte_unmap(pte);
+		spin_unlock(&mm->page_table_lock);
+	}
 out:
 	return referenced;
 }
@@ -502,9 +514,6 @@
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
 	pte_t *pte;
 	pte_t pteval;
 	int ret = SWAP_AGAIN;
@@ -515,30 +524,9 @@
 	if (address == -EFAULT)
 		goto out;
 
-	/*
-	 * We need the page_table_lock to protect us from page faults,
-	 * munmap, fork, etc...
-	 */
-	spin_lock(&mm->page_table_lock);
-
-	pgd = pgd_offset(mm, address);
-	if (!pgd_present(*pgd))
-		goto out_unlock;
-
-	pud = pud_offset(pgd, address);
-	if (!pud_present(*pud))
-		goto out_unlock;
-
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
-		goto out_unlock;
-
-	pte = pte_offset_map(pmd, address);
-	if (!pte_present(*pte))
-		goto out_unmap;
-
-	if (page_to_pfn(page) != pte_pfn(*pte))
-		goto out_unmap;
+	pte = page_check_address(page, mm, address);
+	if (IS_ERR(pte))
+		goto out;
 
 	/*
 	 * If the page is mlock()d, we cannot swap it out.
@@ -604,7 +592,6 @@
 
 out_unmap:
 	pte_unmap(pte);
-out_unlock:
 	spin_unlock(&mm->page_table_lock);
 out:
 	return ret;
@@ -708,7 +695,6 @@
 	}
 
 	pte_unmap(pte);
-
 out_unlock:
 	spin_unlock(&mm->page_table_lock);
 }
@@ -860,3 +846,4 @@
 		ret = SWAP_SUCCESS;
 	return ret;
 }
+
diff --git a/mm/slab.c b/mm/slab.c
index ec660d8..8407426 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -583,7 +583,7 @@
 	return cachep->array[smp_processor_id()];
 }
 
-static inline kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags)
+static inline kmem_cache_t *__find_general_cachep(size_t size, int gfpflags)
 {
 	struct cache_sizes *csizep = malloc_sizes;
 
@@ -607,6 +607,12 @@
 	return csizep->cs_cachep;
 }
 
+kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags)
+{
+	return __find_general_cachep(size, gfpflags);
+}
+EXPORT_SYMBOL(kmem_find_general_cachep);
+
 /* Cal the num objs, wastage, and bytes left over for a given slab size. */
 static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
 		 int flags, size_t *left_over, unsigned int *num)
@@ -672,14 +678,11 @@
 	int memsize = sizeof(void*)*entries+sizeof(struct array_cache);
 	struct array_cache *nc = NULL;
 
-	if (cpu != -1) {
-		kmem_cache_t *cachep;
-		cachep = kmem_find_general_cachep(memsize, GFP_KERNEL);
-		if (cachep)
-			nc = kmem_cache_alloc_node(cachep, cpu_to_node(cpu));
-	}
-	if (!nc)
+	if (cpu == -1)
 		nc = kmalloc(memsize, GFP_KERNEL);
+	else
+		nc = kmalloc_node(memsize, GFP_KERNEL, cpu_to_node(cpu));
+
 	if (nc) {
 		nc->avail = 0;
 		nc->limit = entries;
@@ -1663,7 +1666,7 @@
 	}
 
 	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
-		synchronize_kernel();
+		synchronize_rcu();
 
 	/* no cpu_online check required here since we clear the percpu
 	 * array on cpu offline and set this to NULL.
@@ -2361,7 +2364,7 @@
  * and can sleep. And it will allocate memory on the given node, which
  * can improve the performance for cpu bound structures.
  */
-void *kmem_cache_alloc_node(kmem_cache_t *cachep, int nodeid)
+void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
 {
 	int loop;
 	void *objp;
@@ -2393,7 +2396,7 @@
 		spin_unlock_irq(&cachep->spinlock);
 
 		local_irq_disable();
-		if (!cache_grow(cachep, GFP_KERNEL, nodeid)) {
+		if (!cache_grow(cachep, flags, nodeid)) {
 			local_irq_enable();
 			return NULL;
 		}
@@ -2435,6 +2438,16 @@
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node);
 
+void *kmalloc_node(size_t size, int flags, int node)
+{
+	kmem_cache_t *cachep;
+
+	cachep = kmem_find_general_cachep(size, flags);
+	if (unlikely(cachep == NULL))
+		return NULL;
+	return kmem_cache_alloc_node(cachep, flags, node);
+}
+EXPORT_SYMBOL(kmalloc_node);
 #endif
 
 /**
@@ -2462,7 +2475,12 @@
 {
 	kmem_cache_t *cachep;
 
-	cachep = kmem_find_general_cachep(size, flags);
+	/* If you want to save a few bytes .text space: replace
+	 * __ with kmem_.
+	 * Then kmalloc uses the uninlined functions instead of the inline
+	 * functions.
+	 */
+	cachep = __find_general_cachep(size, flags);
 	if (unlikely(cachep == NULL))
 		return NULL;
 	return __cache_alloc(cachep, flags);
@@ -2489,9 +2507,8 @@
 	for (i = 0; i < NR_CPUS; i++) {
 		if (!cpu_possible(i))
 			continue;
-		pdata->ptrs[i] = kmem_cache_alloc_node(
-				kmem_find_general_cachep(size, GFP_KERNEL),
-				cpu_to_node(i));
+		pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL,
+						cpu_to_node(i));
 
 		if (!pdata->ptrs[i])
 			goto unwind_oom;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index a063a90..4f25177 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -143,7 +143,6 @@
 int add_to_swap(struct page * page)
 {
 	swp_entry_t entry;
-	int pf_flags;
 	int err;
 
 	if (!PageLocked(page))
@@ -154,29 +153,19 @@
 		if (!entry.val)
 			return 0;
 
-		/* Radix-tree node allocations are performing
-		 * GFP_ATOMIC allocations under PF_MEMALLOC.  
-		 * They can completely exhaust the page allocator.  
+		/*
+		 * Radix-tree node allocations from PF_MEMALLOC contexts could
+		 * completely exhaust the page allocator. __GFP_NOMEMALLOC
+		 * stops emergency reserves from being allocated.
 		 *
-		 * So PF_MEMALLOC is dropped here.  This causes the slab 
-		 * allocations to fail earlier, so radix-tree nodes will 
-		 * then be allocated from the mempool reserves.
-		 *
-		 * We're still using __GFP_HIGH for radix-tree node
-		 * allocations, so some of the emergency pools are available,
-		 * just not all of them.
+		 * TODO: this could cause a theoretical memory reclaim
+		 * deadlock in the swap out path.
 		 */
-
-		pf_flags = current->flags;
-		current->flags &= ~PF_MEMALLOC;
-
 		/*
 		 * Add it to the swap cache and mark it dirty
 		 */
-		err = __add_to_swap_cache(page, entry, GFP_ATOMIC|__GFP_NOWARN);
-
-		if (pf_flags & PF_MEMALLOC)
-			current->flags |= PF_MEMALLOC;
+		err = __add_to_swap_cache(page, entry,
+				GFP_ATOMIC|__GFP_NOMEMALLOC|__GFP_NOWARN);
 
 		switch (err) {
 		case 0:				/* Success */
diff --git a/mm/truncate.c b/mm/truncate.c
index c9a63f0..60c8764 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -242,7 +242,7 @@
 
 /**
  * invalidate_inode_pages2_range - remove range of pages from an address_space
- * @mapping - the address_space
+ * @mapping: the address_space
  * @start: the page offset 'from' which to invalidate
  * @end: the page offset 'to' which to invalidate (inclusive)
  *
@@ -322,7 +322,7 @@
 
 /**
  * invalidate_inode_pages2 - remove all pages from an address_space
- * @mapping - the address_space
+ * @mapping: the address_space
  *
  * Any pages which are found to be mapped into pagetables are unmapped prior to
  * invalidation.
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index c6182f6..2bd83e5 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -475,6 +475,10 @@
 
 EXPORT_SYMBOL(vmalloc);
 
+#ifndef PAGE_KERNEL_EXEC
+# define PAGE_KERNEL_EXEC PAGE_KERNEL
+#endif
+
 /**
  *	vmalloc_exec  -  allocate virtually contiguous, executable memory
  *
@@ -488,10 +492,6 @@
  *	use __vmalloc() instead.
  */
 
-#ifndef PAGE_KERNEL_EXEC
-# define PAGE_KERNEL_EXEC PAGE_KERNEL
-#endif
-
 void *vmalloc_exec(unsigned long size)
 {
 	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
diff --git a/net/802/fddi.c b/net/802/fddi.c
index f9a31a9..ebcf483 100644
--- a/net/802/fddi.c
+++ b/net/802/fddi.c
@@ -10,7 +10,7 @@
  * Authors:	Lawrence V. Stefani, <stefani@lkg.dec.com>
  *
  *		fddi.c is based on previous eth.c and tr.c work by
- *			Ross Biro, <bir7@leland.Stanford.Edu>
+ *			Ross Biro
  *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *			Mark Evans, <evansmp@uhura.aston.ac.uk>
  *			Florian La Roche, <rzsfl@rz.uni-sb.de>
diff --git a/net/802/hippi.c b/net/802/hippi.c
index 4eb135c..051e8af 100644
--- a/net/802/hippi.c
+++ b/net/802/hippi.c
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)hippi.c	1.0.0	05/29/97
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Florian  La Roche, <rzsfl@rz.uni-sb.de>
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index c32d27a..7b214cf 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -23,7 +23,7 @@
 #include <linux/errno.h>	/* return codes */
 #include <linux/kernel.h>
 #include <linux/slab.h>		/* kmalloc(), kfree() */
-#include <linux/mm.h>		/* verify_area(), etc. */
+#include <linux/mm.h>
 #include <linux/string.h>	/* inline mem*, str* functions */
 #include <linux/init.h>		/* __initfunc et al. */
 #include <asm/byteorder.h>	/* htons(), etc. */
diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c
index 7659844..1237e20 100644
--- a/net/appletalk/dev.c
+++ b/net/appletalk/dev.c
@@ -19,7 +19,7 @@
 	return -EINVAL;
 }
 
-void ltalk_setup(struct net_device *dev)
+static void ltalk_setup(struct net_device *dev)
 {
 	/* Fill in the fields of the device structure with localtalk-generic values. */
 	
@@ -40,4 +40,22 @@
 
 	dev->flags		= IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
 }
-EXPORT_SYMBOL(ltalk_setup);
+
+/**
+ * alloc_ltalkdev - Allocates and sets up an localtalk device
+ * @sizeof_priv: Size of additional driver-private structure to be allocated
+ *	for this localtalk device
+ *
+ * Fill in the fields of the device structure with localtalk-generic
+ * values. Basically does everything except registering the device.
+ *
+ * Constructs a new net device, complete with a private data area of
+ * size @sizeof_priv.  A 32-byte (not bit) alignment is enforced for
+ * this private data area.
+ */
+
+struct net_device *alloc_ltalkdev(int sizeof_priv)
+{
+	return alloc_netdev(sizeof_priv, "lt%d", ltalk_setup);
+}
+EXPORT_SYMBOL(alloc_ltalkdev);
diff --git a/net/atm/common.c b/net/atm/common.c
index 6d16be3..e93e838 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -12,7 +12,7 @@
 #include <linux/socket.h>	/* SOL_SOCKET */
 #include <linux/errno.h>	/* error codes */
 #include <linux/capability.h>
-#include <linux/mm.h>		/* verify_area */
+#include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/time.h>		/* struct timeval */
 #include <linux/skbuff.h>
@@ -540,7 +540,7 @@
 		error = -EMSGSIZE;
 		goto out;
 	}
-	/* verify_area is done by net/socket.c */
+
 	eff = (size+3) & ~3; /* align to word boundary */
 	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	error = 0;
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 33f1685..a57a926 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -44,11 +44,6 @@
 	return dev;
 }
 
-static void __free_atm_dev(struct atm_dev *dev)
-{
-	kfree(dev);
-}
-
 static struct atm_dev *__atm_dev_lookup(int number)
 {
 	struct atm_dev *dev;
@@ -90,7 +85,7 @@
 		if ((inuse = __atm_dev_lookup(number))) {
 			atm_dev_put(inuse);
 			spin_unlock(&atm_dev_lock);
-			__free_atm_dev(dev);
+			kfree(dev);
 			return NULL;
 		}
 		dev->number = number;
@@ -119,7 +114,7 @@
 		spin_lock(&atm_dev_lock);
 		list_del(&dev->dev_list);
 		spin_unlock(&atm_dev_lock);
-		__free_atm_dev(dev);
+		kfree(dev);
 		return NULL;
 	}
 
@@ -148,7 +143,7 @@
                 }
         }
 
-	__free_atm_dev(dev);
+	kfree(dev);
 }
 
 void shutdown_atm_dev(struct atm_dev *dev)
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index 6ff8031..f7c449a 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -134,6 +134,7 @@
 			break;
 		case as_indicate:
 			vcc = *(struct atm_vcc **) &msg->listen_vcc;
+			sk = sk_atm(vcc);
 			DPRINTK("as_indicate!!!\n");
 			lock_sock(sk);
 			if (sk_acceptq_is_full(sk)) {
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 33b1a37..707097d 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1587,9 +1587,7 @@
 	*asmptr = AX25_UI;
 
 	/* Datagram frames go straight out of the door as UI */
-	skb->dev = ax25->ax25_dev->dev;
-
-	ax25_queue_xmit(skb);
+	ax25_queue_xmit(skb, ax25->ax25_dev->dev);
 
 	err = len;
 
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
index 10ffd2b..1d4ab64 100644
--- a/net/ax25/ax25_ds_subr.c
+++ b/net/ax25/ax25_ds_subr.c
@@ -143,8 +143,7 @@
 	*p++ = cmd;
 	*p++ = param;
 
-	skb->dev      = ax25_dev->dev;
-	skb->protocol = htons(ETH_P_AX25);
+	skb->protocol = ax25_type_trans(skb, ax25_dev->dev);
 
 	dev_queue_xmit(skb);
 }
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index 04d7113..bba0173 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -199,9 +199,7 @@
 		skb = ourskb;
 	}
 
-	skb->dev      = dev;
-
-	ax25_queue_xmit(skb);
+	ax25_queue_xmit(skb, dev);
 
 put:
 	ax25_put_route(route);
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 3475a3a..5fc048d 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -340,21 +340,18 @@
 
 	ax25_addr_build(ptr, &ax25->source_addr, &ax25->dest_addr, ax25->digipeat, type, ax25->modulus);
 
-	skb->dev = ax25->ax25_dev->dev;
-
-	ax25_queue_xmit(skb);
+	ax25_queue_xmit(skb, ax25->ax25_dev->dev);
 }
 
 /*
  *	A small shim to dev_queue_xmit to add the KISS control byte, and do
  *	any packet forwarding in operation.
  */
-void ax25_queue_xmit(struct sk_buff *skb)
+void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	unsigned char *ptr;
 
-	skb->protocol = htons(ETH_P_AX25);
-	skb->dev      = ax25_fwd_dev(skb->dev);
+	skb->protocol = ax25_type_trans(skb, ax25_fwd_dev(dev));
 
 	ptr  = skb_push(skb, 1);
 	*ptr = 0x00;			/* KISS */
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 8cf7270..99694b5 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -220,9 +220,7 @@
 	dptr  = skb_push(skb, ax25_addr_size(digi));
 	dptr += ax25_addr_build(dptr, dest, src, &retdigi, AX25_RESPONSE, AX25_MODULUS);
 
-	skb->dev      = dev;
-
-	ax25_queue_xmit(skb);
+	ax25_queue_xmit(skb, dev);
 }
 
 /*
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 1650c6b..12b4334 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -31,7 +31,6 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 9a8d99a..9778c6a 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -34,7 +34,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 1e5c030..b2e7e38 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 20ce04f..2e341de 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 4c7f9e2..beb045b 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 71762d7..a31244e 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -30,7 +30,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 860dba7..fb55243 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -31,7 +31,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 8ccba8e..c4b592b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -30,7 +30,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index c9792ba..ebdcce5 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -30,7 +30,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 2cf98ce..affbc55 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index fabb36d..f8986f8 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index c12babc..32fccfb 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -30,7 +30,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 640028a..f3f6355 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 3e750ef..746c11f 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -30,7 +30,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
diff --git a/net/core/datagram.c b/net/core/datagram.c
index d1bfd27..fcee054 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -115,10 +115,10 @@
 
 /**
  *	skb_recv_datagram - Receive a datagram skbuff
- *	@sk - socket
- *	@flags - MSG_ flags
- *	@noblock - blocking operation?
- *	@err - error code returned
+ *	@sk: socket
+ *	@flags: MSG_ flags
+ *	@noblock: blocking operation?
+ *	@err: error code returned
  *
  *	Get a datagram skbuff, understands the peeking, nonblocking wakeups
  *	and possible races. This replaces identical code in packet, raw and
@@ -201,10 +201,10 @@
 
 /**
  *	skb_copy_datagram_iovec - Copy a datagram to an iovec.
- *	@skb - buffer to copy
- *	@offset - offset in the buffer to start copying from
- *	@iovec - io vector to copy to
- *	@len - amount of data to copy from buffer to iovec
+ *	@skb: buffer to copy
+ *	@offset: offset in the buffer to start copying from
+ *	@to: io vector to copy to
+ *	@len: amount of data to copy from buffer to iovec
  *
  *	Note: the iovec is modified during the copy.
  */
@@ -377,9 +377,9 @@
 
 /**
  *	skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec.
- *	@skb - skbuff
- *	@hlen - hardware length
- *	@iovec - io vector
+ *	@skb: skbuff
+ *	@hlen: hardware length
+ *	@iov: io vector
  * 
  *	Caller _must_ check that skb will fit to this iovec.
  *
@@ -425,9 +425,9 @@
 
 /**
  * 	datagram_poll - generic datagram poll
- *	@file - file struct
- *	@sock - socket
- *	@wait - poll table
+ *	@file: file struct
+ *	@sock: socket
+ *	@wait: poll table
  *
  *	Datagram poll: Again totally generic. This also handles
  *	sequenced packet sockets providing the socket receive queue
diff --git a/net/core/dev.c b/net/core/dev.c
index 42344d9..d4d9e26 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7,7 +7,7 @@
  *		2 of the License, or (at your option) any later version.
  *
  *	Derived from the non IP parts of dev.c 1.0.19
- * 		Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * 		Authors:	Ross Biro
  *				Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *				Mark Evans, <evansmp@uhura.aston.ac.uk>
  *
@@ -1214,6 +1214,19 @@
  *	A negative errno code is returned on a failure. A success does not
  *	guarantee the frame will be transmitted as it may be dropped due
  *	to congestion or traffic shaping.
+ *
+ * -----------------------------------------------------------------------------------
+ *      I notice this method can also return errors from the queue disciplines,
+ *      including NET_XMIT_DROP, which is a positive value.  So, errors can also
+ *      be positive.
+ *
+ *      Regardless of the return value, the skb is consumed, so it is currently
+ *      difficult to retry a send to this method.  (You can bump the ref count
+ *      before sending to hold a reference for retry if you are careful.)
+ *
+ *      When calling this method, interrupts MUST be enabled.  This is because
+ *      the BH enable code must have IRQs enabled so that it will not deadlock.
+ *          --BLG
  */
 
 int dev_queue_xmit(struct sk_buff *skb)
@@ -3078,7 +3091,7 @@
 void synchronize_net(void) 
 {
 	might_sleep();
-	synchronize_kernel();
+	synchronize_rcu();
 }
 
 /**
diff --git a/net/core/iovec.c b/net/core/iovec.c
index d57ace9..65e4b56 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -33,7 +33,7 @@
  *	Verify iovec. The caller must ensure that the iovec is big enough
  *	to hold the message iovec.
  *
- *	Save time not doing verify_area. copy_*_user will make this work
+ *	Save time not doing access_ok. copy_*_user will make this work
  *	in any case.
  */
 
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 4859b74..d43d120 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -16,6 +16,7 @@
 #include <linux/netdevice.h>
 #include <linux/if.h>
 #include <net/sock.h>
+#include <net/pkt_sched.h>
 #include <linux/rtnetlink.h>
 #include <linux/jiffies.h>
 #include <linux/spinlock.h>
@@ -74,6 +75,12 @@
 		clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
 
 		if (dev->flags & IFF_UP) {
+			if (netif_carrier_ok(dev)) {
+				WARN_ON(dev->qdisc_sleeping == &noop_qdisc);
+				dev_activate(dev);
+			} else
+				dev_deactivate(dev);
+
 			netdev_state_change(dev);
 		}
 
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0a2f67b..43bdc52 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1953,7 +1953,7 @@
 	struct neigh_statistics *st = v;
 
 	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "entries  allocs destroys hash_grows  lookups hits  res_failed  rcv_probes_mcast rcv_probes_ucast  periodic_gc_runs forced_gc_runs forced_gc_goal_miss\n");
+		seq_printf(seq, "entries  allocs destroys hash_grows  lookups hits  res_failed  rcv_probes_mcast rcv_probes_ucast  periodic_gc_runs forced_gc_runs\n");
 		return 0;
 	}
 
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index e51cfa4..22a8f12 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -217,21 +217,10 @@
 	 * NF_IP_RAW_INPUT and NF_IP_PRE_ROUTING.  */
 	if (!skb->dev) {
 		printk("ip_local_deliver: skb->dev is NULL.\n");
-	}
-	else if (strcmp(skb->dev->name, "lo") == 0) {
-		if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
-				      | (1 << NF_IP_POST_ROUTING)
-				      | (1 << NF_IP_PRE_ROUTING)
-				      | (1 << NF_IP_LOCAL_IN))) {
-			printk("ip_local_deliver: bad loopback skb: ");
-			debug_print_hooks_ip(skb->nf_debug);
-			nf_dump_skb(PF_INET, skb);
-		}
-	}
-	else {
+	} else {
 		if (skb->nf_debug != ((1<<NF_IP_PRE_ROUTING)
 				      | (1<<NF_IP_LOCAL_IN))) {
-			printk("ip_local_deliver: bad non-lo skb: ");
+			printk("ip_local_deliver: bad skb: ");
 			debug_print_hooks_ip(skb->nf_debug);
 			nf_dump_skb(PF_INET, skb);
 		}
@@ -247,8 +236,6 @@
 		debug_print_hooks_ip(newskb->nf_debug);
 		nf_dump_skb(PF_INET, newskb);
 	}
-	/* Clear to avoid confusing input check */
-	newskb->nf_debug = 0;
 }
 
 void nf_debug_ip_finish_output2(struct sk_buff *skb)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 44dfaf8..00caf4b 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -22,7 +22,6 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
@@ -87,30 +86,33 @@
 
 struct rtnetlink_link * rtnetlink_links[NPROTO];
 
-static const int rtm_min[(RTM_MAX+1-RTM_BASE)/4] =
+static const int rtm_min[RTM_NR_FAMILIES] =
 {
-	NLMSG_LENGTH(sizeof(struct ifinfomsg)),
-	NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
-	NLMSG_LENGTH(sizeof(struct rtmsg)),
-	NLMSG_LENGTH(sizeof(struct ndmsg)),
-	NLMSG_LENGTH(sizeof(struct rtmsg)),
-	NLMSG_LENGTH(sizeof(struct tcmsg)),
-	NLMSG_LENGTH(sizeof(struct tcmsg)),
-	NLMSG_LENGTH(sizeof(struct tcmsg)),
-	NLMSG_LENGTH(sizeof(struct tcamsg))
+	[RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+	[RTM_FAM(RTM_NEWADDR)]      = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
+	[RTM_FAM(RTM_NEWROUTE)]     = NLMSG_LENGTH(sizeof(struct rtmsg)),
+	[RTM_FAM(RTM_NEWNEIGH)]     = NLMSG_LENGTH(sizeof(struct ndmsg)),
+	[RTM_FAM(RTM_NEWRULE)]      = NLMSG_LENGTH(sizeof(struct rtmsg)),
+	[RTM_FAM(RTM_NEWQDISC)]     = NLMSG_LENGTH(sizeof(struct tcmsg)),
+	[RTM_FAM(RTM_NEWTCLASS)]    = NLMSG_LENGTH(sizeof(struct tcmsg)),
+	[RTM_FAM(RTM_NEWTFILTER)]   = NLMSG_LENGTH(sizeof(struct tcmsg)),
+	[RTM_FAM(RTM_NEWACTION)]    = NLMSG_LENGTH(sizeof(struct tcamsg)),
+	[RTM_FAM(RTM_NEWPREFIX)]    = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+	[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+	[RTM_FAM(RTM_GETANYCAST)]   = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
 };
 
-static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] =
+static const int rta_max[RTM_NR_FAMILIES] =
 {
-	IFLA_MAX,
-	IFA_MAX,
-	RTA_MAX,
-	NDA_MAX,
-	RTA_MAX,
-	TCA_MAX,
-	TCA_MAX,
-	TCA_MAX,
-	TCAA_MAX
+	[RTM_FAM(RTM_NEWLINK)]      = IFLA_MAX,
+	[RTM_FAM(RTM_NEWADDR)]      = IFA_MAX,
+	[RTM_FAM(RTM_NEWROUTE)]     = RTA_MAX,
+	[RTM_FAM(RTM_NEWNEIGH)]     = NDA_MAX,
+	[RTM_FAM(RTM_NEWRULE)]      = RTA_MAX,
+	[RTM_FAM(RTM_NEWQDISC)]     = TCA_MAX,
+	[RTM_FAM(RTM_NEWTCLASS)]    = TCA_MAX,
+	[RTM_FAM(RTM_NEWTFILTER)]   = TCA_MAX,
+	[RTM_FAM(RTM_NEWACTION)]    = TCAA_MAX,
 };
 
 void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
@@ -607,27 +609,33 @@
 
 /*
  *  rtnetlink input queue processing routine:
- *	- try to acquire shared lock. If it is failed, defer processing.
+ *	- process as much as there was in the queue upon entry.
  *	- feed skbs to rtnetlink_rcv_skb, until it refuse a message,
- *	  that will occur, when a dump started and/or acquisition of
- *	  exclusive lock failed.
+ *	  that will occur, when a dump started.
  */
 
 static void rtnetlink_rcv(struct sock *sk, int len)
 {
+	unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
+
 	do {
 		struct sk_buff *skb;
 
-		if (rtnl_shlock_nowait())
-			return;
+		rtnl_lock();
 
-		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+		if (qlen > skb_queue_len(&sk->sk_receive_queue))
+			qlen = skb_queue_len(&sk->sk_receive_queue);
+
+		for (; qlen; qlen--) {
+			skb = skb_dequeue(&sk->sk_receive_queue);
 			if (rtnetlink_rcv_skb(skb)) {
 				if (skb->len)
 					skb_queue_head(&sk->sk_receive_queue,
 						       skb);
-				else
+				else {
 					kfree_skb(skb);
+					qlen--;
+				}
 				break;
 			}
 			kfree_skb(skb);
@@ -636,10 +644,10 @@
 		up(&rtnl_sem);
 
 		netdev_run_todo();
-	} while (rtnl && rtnl->sk_receive_queue.qlen);
+	} while (qlen);
 }
 
-static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
+static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
 {
 	[RTM_GETLINK  - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
 	[RTM_SETLINK  - RTM_BASE] = { .doit   = do_setlink	      },
diff --git a/net/core/scm.c b/net/core/scm.c
index a2ebf30..e887d19 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -15,7 +15,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/stat.h>
 #include <linux/socket.h>
 #include <linux/file.h>
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1b64817..f65b3de 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -86,8 +86,10 @@
  */
 void skb_over_panic(struct sk_buff *skb, int sz, void *here)
 {
-	printk(KERN_INFO "skput:over: %p:%d put:%d dev:%s",
-		here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+	printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p "
+	                  "data:%p tail:%p end:%p dev:%s\n",
+	       here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
+	       skb->dev ? skb->dev->name : "<NULL>");
 	BUG();
 }
 
@@ -102,8 +104,10 @@
 
 void skb_under_panic(struct sk_buff *skb, int sz, void *here)
 {
-	printk(KERN_INFO "skput:under: %p:%d put:%d dev:%s",
-               here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
+	printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p "
+	                  "data:%p tail:%p end:%p dev:%s\n",
+	       here, skb->len, sz, skb->head, skb->data, skb->tail, skb->end,
+	       skb->dev ? skb->dev->name : "<NULL>");
 	BUG();
 }
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 4df4fa3..96e00b0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -9,7 +9,7 @@
  *
  * Version:	$Id: sock.c,v 1.117 2002/02/01 22:01:03 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Florian La Roche, <flla@stud.uni-sb.de>
  *		Alan Cox, <A.Cox@swansea.ac.uk>
@@ -97,7 +97,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -617,10 +616,10 @@
 
 /**
  *	sk_alloc - All socket objects are allocated here
- *	@family - protocol family
- *	@priority - for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
- *	@prot - struct proto associated with this new sock instance
- *	@zero_it - if we should zero the newly allocated sock
+ *	@family: protocol family
+ *	@priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
+ *	@prot: struct proto associated with this new sock instance
+ *	@zero_it: if we should zero the newly allocated sock
  */
 struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it)
 {
@@ -636,7 +635,11 @@
 		if (zero_it) {
 			memset(sk, 0, prot->obj_size);
 			sk->sk_family = family;
-			sk->sk_prot = prot;
+			/*
+			 * See comment in struct sock definition to understand
+			 * why we need sk_prot_creator -acme
+			 */
+			sk->sk_prot = sk->sk_prot_creator = prot;
 			sock_lock_init(sk);
 		}
 		
@@ -655,7 +658,7 @@
 void sk_free(struct sock *sk)
 {
 	struct sk_filter *filter;
-	struct module *owner = sk->sk_prot->owner;
+	struct module *owner = sk->sk_prot_creator->owner;
 
 	if (sk->sk_destruct)
 		sk->sk_destruct(sk);
@@ -673,8 +676,8 @@
 		       __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
 
 	security_sk_free(sk);
-	if (sk->sk_prot->slab != NULL)
-		kmem_cache_free(sk->sk_prot->slab, sk);
+	if (sk->sk_prot_creator->slab != NULL)
+		kmem_cache_free(sk->sk_prot_creator->slab, sk);
 	else
 		kfree(sk);
 	module_put(owner);
@@ -971,8 +974,8 @@
 
 /**
  * sk_wait_data - wait for data to arrive at sk_receive_queue
- * sk - sock to wait on
- * timeo - for how long
+ * @sk:    sock to wait on
+ * @timeo: for how long
  *
  * Now socket state including sk->sk_err is changed only under lock,
  * hence we may omit checks after joining wait queue.
diff --git a/net/core/stream.c b/net/core/stream.c
index 1e27a57..ac9edfd 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -21,7 +21,7 @@
 
 /**
  * sk_stream_write_space - stream socket write_space callback.
- * sk - socket
+ * @sk: socket
  *
  * FIXME: write proper description
  */
@@ -43,8 +43,8 @@
 
 /**
  * sk_stream_wait_connect - Wait for a socket to get into the connected state
- * @sk - sock to wait on
- * @timeo_p - for how long to wait
+ * @sk: sock to wait on
+ * @timeo_p: for how long to wait
  *
  * Must be called with the socket locked.
  */
@@ -79,7 +79,7 @@
 
 /**
  * sk_stream_closing - Return 1 if we still have things to send in our buffers.
- * @sk - socket to verify
+ * @sk: socket to verify
  */
 static inline int sk_stream_closing(struct sock *sk)
 {
@@ -107,8 +107,8 @@
 
 /**
  * sk_stream_wait_memory - Wait for more memory for a socket
- * @sk - socket to wait for memory
- * @timeo_p - for how long
+ * @sk: socket to wait for memory
+ * @timeo_p: for how long
  */
 int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
 {
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index c2a0346..ee7bf46 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -1411,21 +1411,22 @@
 
 #endif /* CONFIG_PROC_FS */
 
-static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] = 
+static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] =
 {
-	 [4] = { .doit   = dn_dev_rtm_newaddr,	},
-	 [5] = { .doit   = dn_dev_rtm_deladdr,	},
-	 [6] = { .dumpit = dn_dev_dump_ifaddr,	},
-
+	[RTM_NEWADDR  - RTM_BASE] = { .doit	= dn_dev_rtm_newaddr,	},
+	[RTM_DELADDR  - RTM_BASE] = { .doit	= dn_dev_rtm_deladdr,	},
+	[RTM_GETADDR  - RTM_BASE] = { .dumpit	= dn_dev_dump_ifaddr,	},
 #ifdef CONFIG_DECNET_ROUTER
-	 [8] = { .doit   = dn_fib_rtm_newroute,	},
-	 [9] = { .doit   = dn_fib_rtm_delroute,	},
-	[10] = { .doit   = dn_cache_getroute, .dumpit = dn_fib_dump, },
-	[16] = { .doit   = dn_fib_rtm_newrule, },
-	[17] = { .doit   = dn_fib_rtm_delrule, },
-	[18] = { .dumpit = dn_fib_dump_rules,  },
+	[RTM_NEWROUTE - RTM_BASE] = { .doit	= dn_fib_rtm_newroute,	},
+	[RTM_DELROUTE - RTM_BASE] = { .doit	= dn_fib_rtm_delroute,	},
+	[RTM_GETROUTE - RTM_BASE] = { .doit	= dn_cache_getroute,
+				      .dumpit	= dn_fib_dump,		},
+	[RTM_NEWRULE  - RTM_BASE] = { .doit	= dn_fib_rtm_newrule,	},
+	[RTM_DELRULE  - RTM_BASE] = { .doit	= dn_fib_rtm_delrule,	},
+	[RTM_GETRULE  - RTM_BASE] = { .dumpit	= dn_fib_dump_rules,	},
 #else
-	[10] = { .doit   = dn_cache_getroute, .dumpit = dn_cache_dump, },
+	[RTM_GETROUTE - RTM_BASE] = { .doit	= dn_cache_getroute,
+				      .dumpit	= dn_cache_dump,	},
 #endif
 
 };
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index f86a625..284a999 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -119,8 +119,9 @@
 static void dnrmg_receive_user_sk(struct sock *sk, int len)
 {
 	struct sk_buff *skb;
+	unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
 
-	while((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+	for (; qlen && (skb = skb_dequeue(&sk->sk_receive_queue)); qlen--) {
 		dnrmg_receive_user_skb(skb);
 		kfree_skb(skb);
 	}
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 16c4234..6617ea4 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -7,7 +7,7 @@
  *
  * Version:	@(#)eth.c	1.0.7	05/25/93
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Florian  La Roche, <rzsfl@rz.uni-sb.de>
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c34dab6..b3cb49c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: af_inet.c,v 1.137 2002/02/01 22:01:03 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Florian La Roche, <flla@stud.uni-sb.de>
  *		Alan Cox, <A.Cox@swansea.ac.uk>
@@ -73,7 +73,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index eea7ef0..3cc9673 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -9,7 +9,7 @@
  *		2 of the License, or (at your option) any later version.
  *
  *	Derived from the IP parts of dev.c 1.0.19
- * 		Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * 		Authors:	Ross Biro
  *				Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *				Mark Evans, <evansmp@uhura.aston.ac.uk>
  *
@@ -1107,17 +1107,18 @@
 	}
 }
 
-static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
-	 [4] = { .doit	 = inet_rtm_newaddr,  },
-	 [5] = { .doit	 = inet_rtm_deladdr,  },
-	 [6] = { .dumpit = inet_dump_ifaddr,  },
-	 [8] = { .doit	 = inet_rtm_newroute, },
-	 [9] = { .doit	 = inet_rtm_delroute, },
-	[10] = { .doit	 = inet_rtm_getroute, .dumpit = inet_dump_fib, },
+static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = {
+	[RTM_NEWADDR  - RTM_BASE] = { .doit	= inet_rtm_newaddr,	},
+	[RTM_DELADDR  - RTM_BASE] = { .doit	= inet_rtm_deladdr,	},
+	[RTM_GETADDR  - RTM_BASE] = { .dumpit	= inet_dump_ifaddr,	},
+	[RTM_NEWROUTE - RTM_BASE] = { .doit	= inet_rtm_newroute,	},
+	[RTM_DELROUTE - RTM_BASE] = { .doit	= inet_rtm_delroute,	},
+	[RTM_GETROUTE - RTM_BASE] = { .doit	= inet_rtm_getroute,
+				      .dumpit	= inet_dump_fib,	},
 #ifdef CONFIG_IP_MULTIPLE_TABLES
-	[16] = { .doit	 = inet_rtm_newrule, },
-	[17] = { .doit	 = inet_rtm_delrule, },
-	[18] = { .dumpit = inet_dump_rules,  },
+	[RTM_NEWRULE  - RTM_BASE] = { .doit	= inet_rtm_newrule,	},
+	[RTM_DELRULE  - RTM_BASE] = { .doit	= inet_rtm_delrule,	},
+	[RTM_GETRULE  - RTM_BASE] = { .dumpit	= inet_dump_rules,	},
 #endif
 };
 
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index a0d0833..4e47a26 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: ip_input.c,v 1.55 2002/01/12 07:39:45 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Donald Becker, <becker@super.org>
  *		Alan Cox, <Alan.Cox@linux.org>
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 30ab7b6..daebd93 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: ip_output.c,v 1.100 2002/02/01 22:01:03 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Donald Becker, <becker@super.org>
  *		Alan Cox, <Alan.Cox@linux.org>
@@ -111,6 +111,7 @@
 #ifdef CONFIG_NETFILTER_DEBUG
 	nf_debug_ip_loopback_xmit(newskb);
 #endif
+	nf_reset(newskb);
 	netif_rx(newskb);
 	return 0;
 }
@@ -195,6 +196,8 @@
 	nf_debug_ip_finish_output2(skb);
 #endif /*CONFIG_NETFILTER_DEBUG*/
 
+	nf_reset(skb);
+
 	if (hh) {
 		int hh_alen;
 
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index 10b23e1..c3d2ca1 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -172,7 +172,7 @@
 		    multipath_comparekeys(&rt->fl, flp)) {
 			struct multipath_candidate* mpc =
 				(struct multipath_candidate*)
-				kmalloc(size_mpc, GFP_KERNEL);
+				kmalloc(size_mpc, GFP_ATOMIC);
 
 			if (!mpc)
 				return;
@@ -244,7 +244,7 @@
 	if (!target_route) {
 		const size_t size_rt = sizeof(struct multipath_route);
 		target_route = (struct multipath_route *)
-			kmalloc(size_rt, GFP_KERNEL);
+			kmalloc(size_rt, GFP_ATOMIC);
 
 		target_route->gw = nh->nh_gw;
 		target_route->oif = nh->nh_oif;
@@ -265,7 +265,7 @@
 	if (!target_dest) {
 		const size_t size_dst = sizeof(struct multipath_dest);
 		target_dest = (struct multipath_dest*)
-			kmalloc(size_dst, GFP_KERNEL);
+			kmalloc(size_dst, GFP_ATOMIC);
 
 		target_dest->nh_info = nh;
 		target_dest->network = network;
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 12b88cb..dd86503 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -252,7 +252,7 @@
 }
 
 /* Look up to see if we're just after a \n. */
-static int find_nl_seq(u16 seq, const struct ip_ct_ftp_master *info, int dir)
+static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir)
 {
 	unsigned int i;
 
@@ -263,7 +263,7 @@
 }
 
 /* We don't update if it's older than what we have. */
-static void update_nl_seq(u16 nl_seq, struct ip_ct_ftp_master *info, int dir)
+static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir)
 {
 	unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
 
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e800b16..721ddbf 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -770,6 +770,7 @@
 {
 	[TH_SYN]			= 1,
 	[TH_SYN|TH_ACK]			= 1,
+	[TH_SYN|TH_ACK|TH_PUSH]		= 1,
 	[TH_RST]			= 1,
 	[TH_RST|TH_ACK]			= 1,
 	[TH_RST|TH_ACK|TH_PUSH]		= 1,
@@ -818,6 +819,7 @@
 	 */
 	/* FIXME: Source route IP option packets --RR */
 	if (hooknum == NF_IP_PRE_ROUTING
+	    && skb->ip_summed != CHECKSUM_UNNECESSARY
 	    && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
 			         skb->ip_summed == CHECKSUM_HW ? skb->csum
 			      	 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 80a7bde..46ca45f 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -401,6 +401,16 @@
 			       const struct net_device *out,
 			       int (*okfn)(struct sk_buff *))
 {
+	/* We've seen it coming out the other side: confirm it */
+	return ip_conntrack_confirm(pskb);
+}
+
+static unsigned int ip_conntrack_help(unsigned int hooknum,
+				      struct sk_buff **pskb,
+				      const struct net_device *in,
+				      const struct net_device *out,
+				      int (*okfn)(struct sk_buff *))
+{
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
 
@@ -412,9 +422,7 @@
 		if (ret != NF_ACCEPT)
 			return ret;
 	}
-
-	/* We've seen it coming out the other side: confirm it */
-	return ip_conntrack_confirm(pskb);
+	return NF_ACCEPT;
 }
 
 static unsigned int ip_conntrack_defrag(unsigned int hooknum,
@@ -423,13 +431,6 @@
 				        const struct net_device *out,
 				        int (*okfn)(struct sk_buff *))
 {
-#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
-	/* Previously seen (loopback)?  Ignore.  Do this before
-           fragment check. */
-	if ((*pskb)->nfct)
-		return NF_ACCEPT;
-#endif
-
 	/* Gather fragments. */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
 		*pskb = ip_ct_gather_frags(*pskb,
@@ -516,13 +517,30 @@
 	.priority	= NF_IP_PRI_CONNTRACK,
 };
 
+/* helpers */
+static struct nf_hook_ops ip_conntrack_helper_out_ops = {
+	.hook		= ip_conntrack_help,
+	.owner		= THIS_MODULE,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_POST_ROUTING,
+	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+};
+
+static struct nf_hook_ops ip_conntrack_helper_in_ops = {
+	.hook		= ip_conntrack_help,
+	.owner		= THIS_MODULE,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_IN,
+	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+};
+
 /* Refragmenter; last chance. */
 static struct nf_hook_ops ip_conntrack_out_ops = {
 	.hook		= ip_refrag,
 	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_LAST,
+	.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
 };
 
 static struct nf_hook_ops ip_conntrack_local_in_ops = {
@@ -530,7 +548,7 @@
 	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_LAST-1,
+	.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
 };
 
 /* Sysctl support */
@@ -831,10 +849,20 @@
 		printk("ip_conntrack: can't register local out hook.\n");
 		goto cleanup_inops;
 	}
+	ret = nf_register_hook(&ip_conntrack_helper_in_ops);
+	if (ret < 0) {
+		printk("ip_conntrack: can't register local in helper hook.\n");
+		goto cleanup_inandlocalops;
+	}
+	ret = nf_register_hook(&ip_conntrack_helper_out_ops);
+	if (ret < 0) {
+		printk("ip_conntrack: can't register postrouting helper hook.\n");
+		goto cleanup_helperinops;
+	}
 	ret = nf_register_hook(&ip_conntrack_out_ops);
 	if (ret < 0) {
 		printk("ip_conntrack: can't register post-routing hook.\n");
-		goto cleanup_inandlocalops;
+		goto cleanup_helperoutops;
 	}
 	ret = nf_register_hook(&ip_conntrack_local_in_ops);
 	if (ret < 0) {
@@ -860,6 +888,10 @@
 	nf_unregister_hook(&ip_conntrack_local_in_ops);
  cleanup_inoutandlocalops:
 	nf_unregister_hook(&ip_conntrack_out_ops);
+ cleanup_helperoutops:
+	nf_unregister_hook(&ip_conntrack_helper_out_ops);
+ cleanup_helperinops:
+	nf_unregister_hook(&ip_conntrack_helper_in_ops);
  cleanup_inandlocalops:
 	nf_unregister_hook(&ip_conntrack_local_out_ops);
  cleanup_inops:
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 162ceac..9fc6f93 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -356,15 +356,6 @@
 	unsigned long statusbit;
 	enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum);
 
-	if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)
-	    && (hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_LOCAL_IN)) {
-		DEBUGP("ip_nat_core: adjusting sequence number\n");
-		/* future: put this in a l4-proto specific function,
-		 * and call this function here. */
-		if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
-			return NF_DROP;
-	}
-
 	if (mtype == IP_NAT_MANIP_SRC)
 		statusbit = IPS_SRC_NAT;
 	else
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index dec4a74..79f56f6 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -230,6 +230,25 @@
 	return ret;
 }
 
+static unsigned int
+ip_nat_adjust(unsigned int hooknum,
+	      struct sk_buff **pskb,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      int (*okfn)(struct sk_buff *))
+{
+	struct ip_conntrack *ct;
+	enum ip_conntrack_info ctinfo;
+
+	ct = ip_conntrack_get(*pskb, &ctinfo);
+	if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+	        DEBUGP("ip_nat_standalone: adjusting sequence number\n");
+	        if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
+	                return NF_DROP;
+	}
+	return NF_ACCEPT;
+}
+
 /* We must be after connection tracking and before packet filtering. */
 
 /* Before packet filtering, change destination */
@@ -250,6 +269,15 @@
 	.priority	= NF_IP_PRI_NAT_SRC,
 };
 
+/* After conntrack, adjust sequence number */
+static struct nf_hook_ops ip_nat_adjust_out_ops = {
+	.hook		= ip_nat_adjust,
+	.owner		= THIS_MODULE,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_POST_ROUTING,
+	.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
+};
+
 /* Before packet filtering, change destination */
 static struct nf_hook_ops ip_nat_local_out_ops = {
 	.hook		= ip_nat_local_fn,
@@ -268,6 +296,16 @@
 	.priority	= NF_IP_PRI_NAT_SRC,
 };
 
+/* After conntrack, adjust sequence number */
+static struct nf_hook_ops ip_nat_adjust_in_ops = {
+	.hook		= ip_nat_adjust,
+	.owner		= THIS_MODULE,
+	.pf		= PF_INET,
+	.hooknum	= NF_IP_LOCAL_IN,
+	.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
+};
+
+
 static int init_or_cleanup(int init)
 {
 	int ret = 0;
@@ -296,10 +334,20 @@
 		printk("ip_nat_init: can't register out hook.\n");
 		goto cleanup_inops;
 	}
+	ret = nf_register_hook(&ip_nat_adjust_in_ops);
+	if (ret < 0) {
+		printk("ip_nat_init: can't register adjust in hook.\n");
+		goto cleanup_outops;
+	}
+	ret = nf_register_hook(&ip_nat_adjust_out_ops);
+	if (ret < 0) {
+		printk("ip_nat_init: can't register adjust out hook.\n");
+		goto cleanup_adjustin_ops;
+	}
 	ret = nf_register_hook(&ip_nat_local_out_ops);
 	if (ret < 0) {
 		printk("ip_nat_init: can't register local out hook.\n");
-		goto cleanup_outops;
+		goto cleanup_adjustout_ops;;
 	}
 	ret = nf_register_hook(&ip_nat_local_in_ops);
 	if (ret < 0) {
@@ -312,6 +360,10 @@
 	nf_unregister_hook(&ip_nat_local_in_ops);
  cleanup_localoutops:
 	nf_unregister_hook(&ip_nat_local_out_ops);
+ cleanup_adjustout_ops:
+	nf_unregister_hook(&ip_nat_adjust_out_ops);
+ cleanup_adjustin_ops:
+	nf_unregister_hook(&ip_nat_adjust_in_ops);
  cleanup_outops:
 	nf_unregister_hook(&ip_nat_out_ops);
  cleanup_inops:
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 9e40dff..e5746b6 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -546,20 +546,18 @@
 static void
 ipq_rcv_sk(struct sock *sk, int len)
 {
-	do {
-		struct sk_buff *skb;
+	struct sk_buff *skb;
+	unsigned int qlen;
 
-		if (down_trylock(&ipqnl_sem))
-			return;
+	down(&ipqnl_sem);
 			
-		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-			ipq_rcv_skb(skb);
-			kfree_skb(skb);
-		}
+	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+		skb = skb_dequeue(&sk->sk_receive_queue);
+		ipq_rcv_skb(skb);
+		kfree_skb(skb);
+	}
 		
-		up(&ipqnl_sem);
-
-	} while (ipqnl && ipqnl->sk_receive_queue.qlen);
+	up(&ipqnl_sem);
 }
 
 static int
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 01b4a3c..47449ba 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -103,13 +103,15 @@
 	  .hook = ipt_hook, 
 	  .pf = PF_INET, 
 	  .hooknum = NF_IP_PRE_ROUTING, 
-	  .priority = NF_IP_PRI_RAW
+	  .priority = NF_IP_PRI_RAW,
+	  .owner = THIS_MODULE,
 	},
 	{
 	  .hook = ipt_hook, 
 	  .pf = PF_INET, 
 	  .hooknum = NF_IP_LOCAL_OUT, 
-	  .priority = NF_IP_PRI_RAW
+	  .priority = NF_IP_PRI_RAW,
+	  .owner = THIS_MODULE,
 	},
 };
 
diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c
index 90a587c..0db405a 100644
--- a/net/ipv4/protocol.c
+++ b/net/ipv4/protocol.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: protocol.c,v 1.14 2001/05/18 02:25:49 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  * Fixes:
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 93624a32..5b1ec58 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: raw.c,v 1.64 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  * Fixes:
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index bb90a0c..a682d28 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: route.c,v 1.103 2002/01/12 07:44:09 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
  *		Linus Torvalds, <Linus.Torvalds@helsinki.fi>
@@ -397,7 +397,7 @@
 	struct rt_cache_stat *st = v;
 
 	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "entries  in_hit in_slow_tot in_no_route in_brd in_martian_dst in_martian_src  out_hit out_slow_tot out_slow_mc  gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n");
+		seq_printf(seq, "entries  in_hit in_slow_tot in_slow_mc in_no_route in_brd in_martian_dst in_martian_src  out_hit out_slow_tot out_slow_mc  gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n");
 		return 0;
 	}
 	
@@ -2843,7 +2843,7 @@
 		.procname	= "flush",
 		.data		= &flush_delay,
 		.maxlen		= sizeof(int),
-		.mode		= 0644,
+		.mode		= 0200,
 		.proc_handler	= &ipv4_sysctl_rtcache_flush,
 		.strategy	= &ipv4_sysctl_rtcache_flush_strategy,
 	},
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 5cff56a..a037baf 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: tcp.c,v 1.216 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 313c140..8faa894 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -777,8 +777,9 @@
 static void tcpdiag_rcv(struct sock *sk, int len)
 {
 	struct sk_buff *skb;
+	unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
 
-	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+	while (qlen-- && (skb = skb_dequeue(&sk->sk_receive_queue))) {
 		tcpdiag_rcv_skb(skb);
 		kfree_skb(skb);
 	}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2504927..79835a6 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: tcp_input.c,v 1.243 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
@@ -3517,7 +3517,6 @@
 	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
 		goto drop;
 
-	th = skb->h.th;
 	__skb_pull(skb, th->doff*4);
 
 	TCP_ECN_accept_cwr(tp, skb);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3ac6659..dad98e4 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -222,10 +222,13 @@
 		int rover;
 
 		spin_lock(&tcp_portalloc_lock);
-		rover = tcp_port_rover;
+		if (tcp_port_rover < low)
+			rover = low;
+		else
+			rover = tcp_port_rover;
 		do {
 			rover++;
-			if (rover < low || rover > high)
+			if (rover > high)
 				rover = low;
 			head = &tcp_bhash[tcp_bhashfn(rover)];
 			spin_lock(&head->lock);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index fd70509..eea1a17 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: tcp_minisocks.c,v 1.15 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 13c14cb..fa24e7a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: tcp_output.c,v 1.146 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
@@ -427,7 +427,7 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb = sk->sk_send_head;
 
-	if (tcp_snd_test(tp, skb, cur_mss, TCP_NAGLE_PUSH)) {
+	if (tcp_snd_test(sk, skb, cur_mss, TCP_NAGLE_PUSH)) {
 		/* Send it out now. */
 		TCP_SKB_CB(skb)->when = tcp_time_stamp;
 		tcp_tso_set_push(skb);
@@ -440,9 +440,12 @@
 	}
 }
 
-void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
+void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
 {
-	if (skb->len <= mss_std) {
+	struct tcp_sock *tp = tcp_sk(sk);
+
+	if (skb->len <= tp->mss_cache_std ||
+	    !(sk->sk_route_caps & NETIF_F_TSO)) {
 		/* Avoid the costly divide in the normal
 		 * non-TSO case.
 		 */
@@ -451,10 +454,10 @@
 	} else {
 		unsigned int factor;
 
-		factor = skb->len + (mss_std - 1);
-		factor /= mss_std;
+		factor = skb->len + (tp->mss_cache_std - 1);
+		factor /= tp->mss_cache_std;
 		skb_shinfo(skb)->tso_segs = factor;
-		skb_shinfo(skb)->tso_size = mss_std;
+		skb_shinfo(skb)->tso_size = tp->mss_cache_std;
 	}
 }
 
@@ -525,8 +528,8 @@
 	}
 
 	/* Fix up tso_factor for both original and new SKB.  */
-	tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
-	tcp_set_skb_tso_segs(buff, tp->mss_cache_std);
+	tcp_set_skb_tso_segs(sk, skb);
+	tcp_set_skb_tso_segs(sk, buff);
 
 	if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
 		tp->lost_out += tcp_skb_pcount(skb);
@@ -601,7 +604,7 @@
 	 * factor and mss.
 	 */
 	if (tcp_skb_pcount(skb) > 1)
-		tcp_set_skb_tso_segs(skb, tcp_skb_mss(skb));
+		tcp_set_skb_tso_segs(sk, skb);
 
 	return 0;
 }
@@ -752,7 +755,7 @@
 		mss_now = tcp_current_mss(sk, 1);
 
 		while ((skb = sk->sk_send_head) &&
-		       tcp_snd_test(tp, skb, mss_now,
+		       tcp_snd_test(sk, skb, mss_now,
 			       	    tcp_skb_is_last(sk, skb) ? nonagle :
 				    			       TCP_NAGLE_PUSH)) {
 			if (skb->len > mss_now) {
@@ -1676,7 +1679,7 @@
 					tp->mss_cache = tp->mss_cache_std;
 				}
 			} else if (!tcp_skb_pcount(skb))
-				tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+				tcp_set_skb_tso_segs(sk, skb);
 
 			TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
 			TCP_SKB_CB(skb)->when = tcp_time_stamp;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 85b279f..799ebe0 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: tcp_timer.c,v 1.88 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Mark Evans, <evansmp@uhura.aston.ac.uk>
  *		Corey Minyard <wf-rch!minyard@relay.EU.net>
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8a21323..4a6952e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: udp.c,v 1.102 2002/02/01 22:01:04 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  *		Alan Cox, <Alan.Cox@linux.org>
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7fe2afd..b2b60f3 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -8,7 +8,10 @@
  * 	
  */
 
+#include <asm/bug.h>
+#include <linux/compiler.h>
 #include <linux/config.h>
+#include <linux/inetdevice.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 
@@ -152,6 +155,8 @@
 		x->u.rt.rt_dst = rt0->rt_dst;
 		x->u.rt.rt_gateway = rt->rt_gateway;
 		x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
+		x->u.rt.idev = rt0->idev;
+		in_dev_hold(rt0->idev);
 		header_len -= x->u.dst.xfrm->props.header_len;
 		trailer_len -= x->u.dst.xfrm->props.trailer_len;
 	}
@@ -243,11 +248,48 @@
 	path->ops->update_pmtu(path, mtu);
 }
 
+static void xfrm4_dst_destroy(struct dst_entry *dst)
+{
+	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+
+	if (likely(xdst->u.rt.idev))
+		in_dev_put(xdst->u.rt.idev);
+	xfrm_dst_destroy(xdst);
+}
+
+static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+			     int unregister)
+{
+	struct xfrm_dst *xdst;
+
+	if (!unregister)
+		return;
+
+	xdst = (struct xfrm_dst *)dst;
+	if (xdst->u.rt.idev->dev == dev) {
+		struct in_device *loopback_idev = in_dev_get(&loopback_dev);
+		BUG_ON(!loopback_idev);
+
+		do {
+			in_dev_put(xdst->u.rt.idev);
+			xdst->u.rt.idev = loopback_idev;
+			in_dev_hold(loopback_idev);
+			xdst = (struct xfrm_dst *)xdst->u.dst.child;
+		} while (xdst->u.dst.xfrm);
+
+		__in_dev_put(loopback_idev);
+	}
+
+	xfrm_dst_ifdown(dst, dev);
+}
+
 static struct dst_ops xfrm4_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		__constant_htons(ETH_P_IP),
 	.gc =			xfrm4_garbage_collect,
 	.update_pmtu =		xfrm4_update_pmtu,
+	.destroy =		xfrm4_dst_destroy,
+	.ifdown =		xfrm4_dst_ifdown,
 	.gc_thresh =		1024,
 	.entry_size =		sizeof(struct xfrm_dst),
 };
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7196ac2..7744a25 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3076,7 +3076,7 @@
 	netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC);
 }
 
-static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
+static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = {
 	[RTM_GETLINK - RTM_BASE] = { .dumpit	= inet6_dump_ifinfo, },
 	[RTM_NEWADDR - RTM_BASE] = { .doit	= inet6_rtm_newaddr, },
 	[RTM_DELADDR - RTM_BASE] = { .doit	= inet6_rtm_deladdr, },
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 768b117..2b193e3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -28,7 +28,6 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
@@ -88,6 +87,7 @@
 
 #ifdef INET_REFCNT_DEBUG
 atomic_t inet6_sock_nr;
+EXPORT_SYMBOL(inet6_sock_nr);
 #endif
 
 /* The inetsw table contains everything that inet_create needs to
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 6dda815..315bc1fbe 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -41,8 +41,8 @@
  * when Linux implements ESP (and maybe AUTH) headers.
  * --AK
  *
- * This function parses (probably truncated) exthdr set "hdr"
- * of length "len". "nexthdrp" initially points to some place,
+ * This function parses (probably truncated) exthdr set "hdr".
+ * "nexthdrp" initially points to some place,
  * where type of the first header can be found.
  *
  * It skips all well-known exthdrs, and returns pointer to the start
@@ -63,7 +63,7 @@
  * --ANK (980726)
  */
 
-int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
+int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
 {
 	u8 nexthdr = *nexthdrp;
 
@@ -71,13 +71,11 @@
 		struct ipv6_opt_hdr _hdr, *hp;
 		int hdrlen;
 
-		if (len < (int)sizeof(struct ipv6_opt_hdr))
-			return -1;
 		if (nexthdr == NEXTHDR_NONE)
 			return -1;
 		hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
 		if (hp == NULL)
-			BUG();
+			return -1;
 		if (nexthdr == NEXTHDR_FRAGMENT) {
 			unsigned short _frag_off, *fp;
 			fp = skb_header_pointer(skb,
@@ -97,7 +95,6 @@
 			hdrlen = ipv6_optlen(hp); 
 
 		nexthdr = hp->nexthdr;
-		len -= hdrlen;
 		start += hdrlen;
 	}
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 87b9082..8e0f569 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -135,7 +135,7 @@
 	if (len < 0)
 		return 1;
 
-	ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
+	ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr);
 	if (ptr < 0)
 		return 0;
 	if (nexthdr == IPPROTO_ICMPV6) {
@@ -514,7 +514,7 @@
 	nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
 	if (ipv6_ext_hdr(nexthdr)) {
 		/* now skip over extension headers */
-		inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
+		inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
 		if (inner_offset<0)
 			return;
 	} else {
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index c54830b..750943e 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -549,20 +549,18 @@
 static void
 ipq_rcv_sk(struct sock *sk, int len)
 {
-	do {
-		struct sk_buff *skb;
+	struct sk_buff *skb;
+	unsigned int qlen;
 
-		if (down_trylock(&ipqnl_sem))
-			return;
+	down(&ipqnl_sem);
 			
-		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-			ipq_rcv_skb(skb);
-			kfree_skb(skb);
-		}
+	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+		skb = skb_dequeue(&sk->sk_receive_queue);
+		ipq_rcv_skb(skb);
+		kfree_skb(skb);
+	}
 		
-		up(&ipqnl_sem);
-
-	} while (ipqnl && ipqnl->sk_receive_queue.qlen);
+	up(&ipqnl_sem);
 }
 
 static int
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 1352c1d..617645b 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -455,11 +455,11 @@
 static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
 				     struct raw6_sock *rp)
 {
-	struct inet_sock *inet = inet_sk(sk);
 	struct sk_buff *skb;
 	int err = 0;
 	int offset;
 	int len;
+	int total_len;
 	u32 tmp_csum;
 	u16 csum;
 
@@ -470,7 +470,8 @@
 		goto out;
 
 	offset = rp->offset;
-	if (offset >= inet->cork.length - 1) {
+	total_len = inet_sk(sk)->cork.length - (skb->nh.raw - skb->data);
+	if (offset >= total_len - 1) {
 		err = -EINVAL;
 		ip6_flush_pending_frames(sk);
 		goto out;
@@ -514,7 +515,7 @@
 
 	tmp_csum = csum_ipv6_magic(&fl->fl6_src,
 				   &fl->fl6_dst,
-				   inet->cork.length, fl->proto, tmp_csum);
+				   total_len, fl->proto, tmp_csum);
 
 	if (tmp_csum == 0)
 		tmp_csum = -1;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1838029..3bf8a02 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2005,7 +2005,7 @@
 		.procname	=	"flush",
          	.data		=	&flush_delay,
 		.maxlen		=	sizeof(int),
-		.mode		=	0644,
+		.mode		=	0200,
          	.proc_handler	=	&ipv6_sysctl_rtcache_flush
 	},
 	{
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4760c85..0f69e80 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -139,9 +139,12 @@
 		int rover;
 
 		spin_lock(&tcp_portalloc_lock);
-		rover = tcp_port_rover;
+		if (tcp_port_rover < low)
+			rover = low;
+		else
+			rover = tcp_port_rover;
 		do {	rover++;
-			if ((rover < low) || (rover > high))
+			if (rover > high)
 				rover = low;
 			head = &tcp_bhash[tcp_bhashfn(rover)];
 			spin_lock(&head->lock);
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 8a4f37d..4429b1a 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -11,7 +11,11 @@
  * 
  */
 
+#include <asm/bug.h>
+#include <linux/compiler.h>
 #include <linux/config.h>
+#include <linux/netdevice.h>
+#include <net/addrconf.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -166,6 +170,8 @@
 		memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 
 		x->u.rt6.rt6i_dst      = rt0->rt6i_dst;
 		x->u.rt6.rt6i_src      = rt0->rt6i_src;	
+		x->u.rt6.rt6i_idev     = rt0->rt6i_idev;
+		in6_dev_hold(rt0->rt6i_idev);
 		header_len -= x->u.dst.xfrm->props.header_len;
 		trailer_len -= x->u.dst.xfrm->props.trailer_len;
 	}
@@ -251,11 +257,48 @@
 	path->ops->update_pmtu(path, mtu);
 }
 
+static void xfrm6_dst_destroy(struct dst_entry *dst)
+{
+	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+
+	if (likely(xdst->u.rt6.rt6i_idev))
+		in6_dev_put(xdst->u.rt6.rt6i_idev);
+	xfrm_dst_destroy(xdst);
+}
+
+static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+			     int unregister)
+{
+	struct xfrm_dst *xdst;
+
+	if (!unregister)
+		return;
+
+	xdst = (struct xfrm_dst *)dst;
+	if (xdst->u.rt6.rt6i_idev->dev == dev) {
+		struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
+		BUG_ON(!loopback_idev);
+
+		do {
+			in6_dev_put(xdst->u.rt6.rt6i_idev);
+			xdst->u.rt6.rt6i_idev = loopback_idev;
+			in6_dev_hold(loopback_idev);
+			xdst = (struct xfrm_dst *)xdst->u.dst.child;
+		} while (xdst->u.dst.xfrm);
+
+		__in6_dev_put(loopback_idev);
+	}
+
+	xfrm_dst_ifdown(dst, dev);
+}
+
 static struct dst_ops xfrm6_dst_ops = {
 	.family =		AF_INET6,
 	.protocol =		__constant_htons(ETH_P_IPV6),
 	.gc =			xfrm6_garbage_collect,
 	.update_pmtu =		xfrm6_update_pmtu,
+	.destroy =		xfrm6_dst_destroy,
+	.ifdown =		xfrm6_dst_ifdown,
 	.gc_thresh =		1024,
 	.entry_size =		sizeof(struct xfrm_dst),
 };
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index d6ccd32..70543d8 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -470,6 +470,7 @@
 }
 EXPORT_SYMBOL(irda_device_unregister_dongle);
 
+#ifdef CONFIG_ISA_DMA_API
 /*
  * Function setup_dma (idev, buffer, count, mode)
  *
@@ -492,3 +493,4 @@
 	release_dma_lock(flags);
 }
 EXPORT_SYMBOL(irda_setup_dma);
+#endif
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1d5905c..733bf52 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -21,7 +21,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/major.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
@@ -50,6 +49,8 @@
 #include <linux/bitops.h>
 #include <linux/mm.h>
 #include <linux/types.h>
+#include <linux/audit.h>
+
 #include <net/sock.h>
 #include <net/scm.h>
 
@@ -374,7 +375,6 @@
 		nlk->cb->done(nlk->cb);
 		netlink_destroy_callback(nlk->cb);
 		nlk->cb = NULL;
-		__sock_put(sk);
 	}
 	spin_unlock(&nlk->cb_lock);
 
@@ -906,6 +906,7 @@
 	NETLINK_CB(skb).groups	= nlk->groups;
 	NETLINK_CB(skb).dst_pid = dst_pid;
 	NETLINK_CB(skb).dst_groups = dst_groups;
+	NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
 	/* What can I do? Netlink is asynchronous, so that
@@ -1100,7 +1101,6 @@
 	spin_unlock(&nlk->cb_lock);
 
 	netlink_destroy_callback(cb);
-	__sock_put(sk);
 	return 0;
 }
 
@@ -1139,7 +1139,6 @@
 		return -EBUSY;
 	}
 	nlk->cb = cb;
-	sock_hold(sk);
 	spin_unlock(&nlk->cb_lock);
 
 	netlink_dump(sk);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 64acea0..0269616 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: af_packet.c,v 1.61 2002/02/08 03:57:19 davem Exp $
  *
- * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors:	Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
  *
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 3d1d902..b094118 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -185,7 +185,7 @@
 	depends on NET_SCHED
 	help
 	  Say Y here if you want to use the Generic Random Early Detection
-	  (RED) packet scheduling algorithm for some of your network devices
+	  (GRED) packet scheduling algorithm for some of your network devices
 	  (see the top of <file:net/sched/sch_red.c> for details and
 	  references about the algorithm).
 
@@ -506,3 +506,13 @@
 	  Say Y to support traffic policing (bandwidth limits).  Needed for
 	  ingress and egress rate limiting.
 
+config NET_ACT_SIMP
+        tristate "Simple action"
+        depends on NET_CLS_ACT
+        ---help---
+        You must have new iproute2 to use this feature.
+        This adds a very simple action for demonstration purposes
+	The idea is to give action authors a basic example to look at.
+	All this action will do is print on the console the configured
+	policy string followed by _ then packet count.
+
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 431e557..eb3fe58 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -6,13 +6,14 @@
 
 obj-$(CONFIG_NET_SCHED)		+= sch_api.o sch_fifo.o
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
-obj-$(CONFIG_NET_CLS_ACT)       += act_api.o
+obj-$(CONFIG_NET_CLS_ACT)	+= act_api.o
 obj-$(CONFIG_NET_ACT_POLICE)	+= police.o
 obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
-obj-$(CONFIG_NET_ACT_GACT)      += gact.o
-obj-$(CONFIG_NET_ACT_MIRRED)    += mirred.o
-obj-$(CONFIG_NET_ACT_IPT)       += ipt.o
-obj-$(CONFIG_NET_ACT_PEDIT)     += pedit.o
+obj-$(CONFIG_NET_ACT_GACT)	+= gact.o
+obj-$(CONFIG_NET_ACT_MIRRED)	+= mirred.o
+obj-$(CONFIG_NET_ACT_IPT)	+= ipt.o
+obj-$(CONFIG_NET_ACT_PEDIT)	+= pedit.o
+obj-$(CONFIG_NET_ACT_SIMP)	+= simple.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_HPFQ)	+= sch_hpfq.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 5e6cc37..cafcb08 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -171,10 +171,10 @@
 				skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
 				skb->tc_verd = CLR_TC_MUNGED(skb->tc_verd);
 			}
-			if (ret != TC_ACT_PIPE)
-				goto exec_done;
 			if (ret == TC_ACT_REPEAT)
 				goto repeat;	/* we need a ttl - JHS */
+			if (ret != TC_ACT_PIPE)
+				goto exec_done;
 		}
 		act = a->next;
 	}
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index fdfc83a..29d8b9a 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -46,9 +46,11 @@
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
+#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *))
+
 struct fw_head
 {
-	struct fw_filter *ht[256];
+	struct fw_filter *ht[HTSIZE];
 };
 
 struct fw_filter
@@ -69,7 +71,28 @@
 
 static __inline__ int fw_hash(u32 handle)
 {
-	return handle&0xFF;
+	if (HTSIZE == 4096)
+		return ((handle >> 24) & 0xFFF) ^
+		       ((handle >> 12) & 0xFFF) ^
+		       (handle & 0xFFF);
+	else if (HTSIZE == 2048)
+		return ((handle >> 22) & 0x7FF) ^
+		       ((handle >> 11) & 0x7FF) ^
+		       (handle & 0x7FF);
+	else if (HTSIZE == 1024)
+		return ((handle >> 20) & 0x3FF) ^
+		       ((handle >> 10) & 0x3FF) ^
+		       (handle & 0x3FF);
+	else if (HTSIZE == 512)
+		return (handle >> 27) ^
+		       ((handle >> 18) & 0x1FF) ^
+		       ((handle >> 9) & 0x1FF) ^
+		       (handle & 0x1FF);
+	else if (HTSIZE == 256) {
+		u8 *t = (u8 *) &handle;
+		return t[0] ^ t[1] ^ t[2] ^ t[3];
+	} else 
+		return handle & (HTSIZE - 1);
 }
 
 static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
@@ -152,7 +175,7 @@
 	if (head == NULL)
 		return;
 
-	for (h=0; h<256; h++) {
+	for (h=0; h<HTSIZE; h++) {
 		while ((f=head->ht[h]) != NULL) {
 			head->ht[h] = f->next;
 			fw_delete_filter(tp, f);
@@ -291,7 +314,7 @@
 	if (arg->stop)
 		return;
 
-	for (h = 0; h < 256; h++) {
+	for (h = 0; h < HTSIZE; h++) {
 		struct fw_filter *f;
 
 		for (f = head->ht[h]; f; f = f->next) {
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 4323a74..07977f8 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1289,6 +1289,7 @@
 
 subsys_initcall(pktsched_init);
 
+EXPORT_SYMBOL(qdisc_lookup);
 EXPORT_SYMBOL(qdisc_get_rtab);
 EXPORT_SYMBOL(qdisc_put_rtab);
 EXPORT_SYMBOL(register_qdisc);
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 8c01e02..87e48a4 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -179,6 +179,7 @@
 		netif_schedule(dev);
 		return 1;
 	}
+	BUG_ON((int) q->q.qlen < 0);
 	return q->q.qlen;
 }
 
@@ -539,6 +540,10 @@
 		write_unlock_bh(&qdisc_tree_lock);
 	}
 
+	if (!netif_carrier_ok(dev))
+		/* Delay activation until next carrier-on event */
+		return;
+
 	spin_lock_bh(&dev->queue_lock);
 	rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping);
 	if (dev->qdisc != &noqueue_qdisc) {
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index a85935e..558cc08 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -717,6 +717,10 @@
 	if (q->direct_queue.qlen < q->direct_qlen) {
 	    __skb_queue_tail(&q->direct_queue, skb);
 	    q->direct_pkts++;
+	} else {
+	    kfree_skb(skb);
+	    sch->qstats.drops++;
+	    return NET_XMIT_DROP;
 	}
 #ifdef CONFIG_NET_CLS_ACT
     } else if (!cl) {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 31c29de..e0c9fbe 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -138,38 +138,77 @@
 }
 
 /* Put skb in the private delayed queue. */
-static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
+static int netem_delay(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
-	struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
 	psched_tdiff_t td;
 	psched_time_t now;
 	
 	PSCHED_GET_TIME(now);
 	td = tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist);
-	PSCHED_TADD2(now, td, cb->time_to_send);
 	
 	/* Always queue at tail to keep packets in order */
 	if (likely(q->delayed.qlen < q->limit)) {
+		struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+	
+		PSCHED_TADD2(now, td, cb->time_to_send);
+
+		pr_debug("netem_delay: skb=%p now=%llu tosend=%llu\n", skb, 
+			 now, cb->time_to_send);
+	
 		__skb_queue_tail(&q->delayed, skb);
-		if (!timer_pending(&q->timer)) {
-			q->timer.expires = jiffies + PSCHED_US2JIFFIE(td);
-			add_timer(&q->timer);
-		}
 		return NET_XMIT_SUCCESS;
 	}
 
+	pr_debug("netem_delay: queue over limit %d\n", q->limit);
+	sch->qstats.overlimits++;
 	kfree_skb(skb);
 	return NET_XMIT_DROP;
 }
 
+/*
+ *  Move a packet that is ready to send from the delay holding
+ *  list to the underlying qdisc.
+ */
+static int netem_run(struct Qdisc *sch)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
+	psched_time_t now;
+
+	PSCHED_GET_TIME(now);
+
+	skb = skb_peek(&q->delayed);
+	if (skb) {
+		const struct netem_skb_cb *cb
+			= (const struct netem_skb_cb *)skb->cb;
+		long delay 
+			= PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
+		pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay);
+
+		/* if more time remaining? */
+		if (delay > 0) {
+			mod_timer(&q->timer, jiffies + delay);
+			return 1;
+		}
+
+		__skb_unlink(skb, &q->delayed);
+		
+		if (q->qdisc->enqueue(skb, q->qdisc)) {
+			sch->q.qlen--;
+			sch->qstats.drops++;
+		} 
+	}
+
+	return 0;
+}
+
 static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
-	struct sk_buff *skb2;
 	int ret;
 
-	pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
+	pr_debug("netem_enqueue skb=%p\n", skb);
 
 	/* Random packet drop 0 => none, ~0 => all */
 	if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
@@ -180,11 +219,21 @@
 	}
 
 	/* Random duplication */
-	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)
-	    && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-		pr_debug("netem_enqueue: dup %p\n", skb2);
+	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
+		struct sk_buff *skb2;
 
-		if (delay_skb(sch, skb2)) {
+		skb2 = skb_clone(skb, GFP_ATOMIC);
+		if (skb2 && netem_delay(sch, skb2) == NET_XMIT_SUCCESS) {
+			struct Qdisc *qp;
+
+			/* Since one packet can generate two packets in the
+			 * queue, the parent's qlen accounting gets confused,
+			 * so fix it.
+			 */
+			qp = qdisc_lookup(sch->dev, TC_H_MAJ(sch->parent));
+			if (qp)
+				qp->q.qlen++;
+
 			sch->q.qlen++;
 			sch->bstats.bytes += skb2->len;
 			sch->bstats.packets++;
@@ -202,7 +251,8 @@
 		ret = q->qdisc->enqueue(skb, q->qdisc);
 	} else {
 		q->counter = 0;
-		ret = delay_skb(sch, skb);
+		ret = netem_delay(sch, skb);
+		netem_run(sch);
 	}
 
 	if (likely(ret == NET_XMIT_SUCCESS)) {
@@ -212,6 +262,7 @@
 	} else
 		sch->qstats.drops++;
 
+	pr_debug("netem: enqueue ret %d\n", ret);
 	return ret;
 }
 
@@ -241,56 +292,35 @@
 	return len;
 }
 
-/* Dequeue packet.
- *  Move all packets that are ready to send from the delay holding
- *  list to the underlying qdisc, then just call dequeue
- */
 static struct sk_buff *netem_dequeue(struct Qdisc *sch)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
+	int pending;
+
+	pending = netem_run(sch);
 
 	skb = q->qdisc->dequeue(q->qdisc);
-	if (skb) 
+	if (skb) {
+		pr_debug("netem_dequeue: return skb=%p\n", skb);
 		sch->q.qlen--;
+		sch->flags &= ~TCQ_F_THROTTLED;
+	}
+	else if (pending) {
+		pr_debug("netem_dequeue: throttling\n");
+		sch->flags |= TCQ_F_THROTTLED;
+	} 
+
 	return skb;
 }
 
 static void netem_watchdog(unsigned long arg)
 {
 	struct Qdisc *sch = (struct Qdisc *)arg;
-	struct netem_sched_data *q = qdisc_priv(sch);
-	struct net_device *dev = sch->dev;
-	struct sk_buff *skb;
-	psched_time_t now;
 
-	pr_debug("netem_watchdog: fired @%lu\n", jiffies);
-
-	spin_lock_bh(&dev->queue_lock);
-	PSCHED_GET_TIME(now);
-
-	while ((skb = skb_peek(&q->delayed)) != NULL) {
-		const struct netem_skb_cb *cb
-			= (const struct netem_skb_cb *)skb->cb;
-		long delay 
-			= PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
-		pr_debug("netem_watchdog: skb %p@%lu %ld\n",
-			 skb, jiffies, delay);
-
-		/* if more time remaining? */
-		if (delay > 0) {
-			mod_timer(&q->timer, jiffies + delay);
-			break;
-		}
-		__skb_unlink(skb, &q->delayed);
-
-		if (q->qdisc->enqueue(skb, q->qdisc)) {
-			sch->q.qlen--;
-			sch->qstats.drops++;
-		}
-	}
-	qdisc_run(dev);
-	spin_unlock_bh(&dev->queue_lock);
+	pr_debug("netem_watchdog qlen=%d\n", sch->q.qlen);
+	sch->flags &= ~TCQ_F_THROTTLED;
+	netif_schedule(sch->dev);
 }
 
 static void netem_reset(struct Qdisc *sch)
@@ -301,6 +331,7 @@
 	skb_queue_purge(&q->delayed);
 
 	sch->q.qlen = 0;
+	sch->flags &= ~TCQ_F_THROTTLED;
 	del_timer_sync(&q->timer);
 }
 
diff --git a/net/sched/simple.c b/net/sched/simple.c
new file mode 100644
index 0000000..3ab4c67
--- /dev/null
+++ b/net/sched/simple.c
@@ -0,0 +1,93 @@
+/*
+ * net/sched/simp.c	Simple example of an action
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Jamal Hadi Salim (2005)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <net/pkt_sched.h>
+
+#define TCA_ACT_SIMP 22
+
+/* XXX: Hide all these common elements under some macro 
+ * probably
+*/
+#include <linux/tc_act/tc_defact.h>
+#include <net/tc_act/tc_defact.h>
+
+/* use generic hash table with 8 buckets */
+#define MY_TAB_SIZE     8
+#define MY_TAB_MASK     (MY_TAB_SIZE - 1)
+static u32 idx_gen;
+static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(simp_lock);
+
+/* override the defaults */
+#define tcf_st		tcf_defact
+#define tc_st		tc_defact
+#define tcf_t_lock	simp_lock
+#define tcf_ht		tcf_simp_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+#include <net/act_generic.h>
+
+static int tcf_simp(struct sk_buff **pskb, struct tc_action *a)
+{
+	struct sk_buff *skb = *pskb;
+	struct tcf_defact *p = PRIV(a, defact);
+
+	spin_lock(&p->lock);
+	p->tm.lastuse = jiffies;
+	p->bstats.bytes += skb->len;
+	p->bstats.packets++;
+
+	/* print policy string followed by _ then packet count 
+	 * Example if this was the 3rd packet and the string was "hello" 
+	 * then it would look like "hello_3" (without quotes) 
+	 **/
+	printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets);
+	spin_unlock(&p->lock);
+	return p->action;
+}
+
+static struct tc_action_ops act_simp_ops = {
+	.kind = "simple",
+	.type = TCA_ACT_SIMP,
+	.capab = TCA_CAP_NONE,
+	.owner = THIS_MODULE,
+	.act = tcf_simp,
+	tca_use_default_ops
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2005)");
+MODULE_DESCRIPTION("Simple example action");
+MODULE_LICENSE("GPL");
+
+static int __init simp_init_module(void)
+{
+	int ret = tcf_register_action(&act_simp_ops);
+	if (!ret)
+		printk("Simple TC action Loaded\n");
+	return ret;
+}
+
+static void __exit simp_cleanup_module(void)
+{
+	tcf_unregister_action(&act_simp_ops);
+}
+
+module_init(simp_init_module);
+module_exit(simp_cleanup_module);
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 544b750..334f617 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -125,6 +125,7 @@
 		sp->autoclose * HZ;
 
 	/* Use SCTP specific send buffer space queues.  */
+	ep->sndbuf_policy = sctp_sndbuf_policy;
 	sk->sk_write_space = sctp_write_space;
 	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
 
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e42c74e..c9d9ea0 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -496,9 +496,7 @@
 /* Is this a wildcard address? */
 static int sctp_v6_is_any(const union sctp_addr *addr)
 {
-	int type;
-	type = ipv6_addr_type((struct in6_addr *)&addr->v6.sin6_addr);
-	return IPV6_ADDR_ANY == type;
+	return ipv6_addr_any(&addr->v6.sin6_addr);
 }
 
 /* Should this be available for binding?   */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 9013f64..84b5b37 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -313,12 +313,12 @@
 	sk = chunk->skb->sk;
 
 	/* Allocate the new skb.  */
-	nskb = dev_alloc_skb(packet->size);
+	nskb = alloc_skb(packet->size + LL_MAX_HEADER, GFP_ATOMIC);
 	if (!nskb)
 		goto nomem;
 
 	/* Make sure the outbound skb has enough header room reserved. */
-	skb_reserve(nskb, packet->overhead);
+	skb_reserve(nskb, packet->overhead + LL_MAX_HEADER);
 
 	/* Set the owning socket so that we know where to get the
 	 * destination IP address.
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index b9813cf..2e1f9c3 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1043,6 +1043,9 @@
 	sctp_max_retrans_path		= 5;
 	sctp_max_retrans_init		= 8;
 
+	/* Sendbuffer growth	    - do per-socket accounting */
+	sctp_sndbuf_policy		= 0;
+
 	/* HB.interval              - 30 seconds */
 	sctp_hb_interval		= 30 * HZ;
 
@@ -1159,8 +1162,6 @@
 	status = 0;
 out:
 	return status;
-err_add_protocol:
-	proto_unregister(&sctp_prot);
 err_ctl_sock_init:
 	sctp_v6_exit();
 err_v6_init:
@@ -1188,6 +1189,8 @@
 	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 	inet_unregister_protosw(&sctp_seqpacket_protosw);
 	inet_unregister_protosw(&sctp_stream_protosw);
+err_add_protocol:
+	proto_unregister(&sctp_prot);
 	goto out;
 }
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 1db12cc..33ac8bf 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -710,7 +710,9 @@
 	struct sctp_chunk *retval;
 	__u8 flags = 0;
 
-	/* Maybe set the T-bit if we have no association. */
+	/* Set the T-bit if we have no association (vtag will be
+	 * reflected)
+	 */
 	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;
 
 	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0);
@@ -732,7 +734,7 @@
 }
 
 /* Create an ABORT.  Note that we set the T bit if we have no
- * association.
+ * association, except when responding to an INIT (sctpimpguide 2.41).
  */
 struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc,
 			      const struct sctp_chunk *chunk,
@@ -741,8 +743,16 @@
 	struct sctp_chunk *retval;
 	__u8 flags = 0;
 
-	/* Maybe set the T-bit if we have no association.  */
-	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;
+	/* Set the T-bit if we have no association and 'chunk' is not
+	 * an INIT (vtag will be reflected).
+	 */
+	if (!asoc) {
+		if (chunk && chunk->chunk_hdr &&
+		    chunk->chunk_hdr->type == SCTP_CID_INIT)
+			flags = 0;
+		else
+			flags = SCTP_CHUNK_FLAG_T;
+	}
 
 	retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint);
 
@@ -2744,7 +2754,6 @@
 
 	hint = (nstreams + 1) * sizeof(__u32);
 
-	/* Maybe set the T-bit if we have no association.  */
 	retval = sctp_make_chunk(asoc, SCTP_CID_FWD_TSN, 0, hint);
 
 	if (!retval)
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 278c56a..8e01b8f 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -126,15 +126,18 @@
  * should stop the T2-shutdown timer and remove all knowledge of the
  * association (and thus the association enters the CLOSED state).
  *
- * Verification Tag: 8.5.1(C)
+ * Verification Tag: 8.5.1(C), sctpimpguide 2.41.
  * C) Rules for packet carrying SHUTDOWN COMPLETE:
  * ...
- * - The receiver of a SHUTDOWN COMPLETE shall accept the packet if the
- *   Verification Tag field of the packet matches its own tag OR it is
- *   set to its peer's tag and the T bit is set in the Chunk Flags.
- *   Otherwise, the receiver MUST silently discard the packet and take
- *   no further action. An endpoint MUST ignore the SHUTDOWN COMPLETE if
- *   it is not in the SHUTDOWN-ACK-SENT state.
+ * - The receiver of a SHUTDOWN COMPLETE shall accept the packet
+ *   if the Verification Tag field of the packet matches its own tag and
+ *   the T bit is not set
+ *   OR
+ *   it is set to its peer's tag and the T bit is set in the Chunk
+ *   Flags.
+ *   Otherwise, the receiver MUST silently discard the packet
+ *   and take no further action.  An endpoint MUST ignore the
+ *   SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state.
  *
  * Inputs
  * (endpoint, asoc, chunk)
@@ -2858,16 +2861,16 @@
 /*
  * Generate an ABORT in response to a packet.
  *
- * Section: 8.4 Handle "Out of the blue" Packets
+ * Section: 8.4 Handle "Out of the blue" Packets, sctpimpguide 2.41
  *
- * 8) The receiver should respond to the sender of the OOTB packet
- *    with an ABORT.  When sending the ABORT, the receiver of the
- *    OOTB packet MUST fill in the Verification Tag field of the
- *    outbound packet with the value found in the Verification Tag
- *    field of the OOTB packet and set the T-bit in the Chunk Flags
- *    to indicate that no TCB was found.  After sending this ABORT,
- *    the receiver of the OOTB packet shall discard the OOTB packet
- *    and take no further action.
+ * 8) The receiver should respond to the sender of the OOTB packet with
+ *    an ABORT.  When sending the ABORT, the receiver of the OOTB packet
+ *    MUST fill in the Verification Tag field of the outbound packet
+ *    with the value found in the Verification Tag field of the OOTB
+ *    packet and set the T-bit in the Chunk Flags to indicate that the
+ *    Verification Tag is reflected.  After sending this ABORT, the
+ *    receiver of the OOTB packet shall discard the OOTB packet and take
+ *    no further action.
  *
  * Verification Tag:
  *
@@ -2895,6 +2898,10 @@
 			return SCTP_DISPOSITION_NOMEM;
 		}
 
+		/* Reflect vtag if T-Bit is set */
+		if (sctp_test_T_bit(abort))
+			packet->vtag = ntohl(chunk->sctp_hdr->vtag);
+
 		/* Set the skb to the belonging sock for accounting.  */
 		abort->skb->sk = ep->base.sk;
 
@@ -3026,22 +3033,24 @@
 }
 
 /*
- * RFC 2960, 8.4 - Handle "Out of the blue" Packets
+ * RFC 2960, 8.4 - Handle "Out of the blue" Packets, sctpimpguide 2.41.
+ *
  * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should
  *    respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE.
  *    When sending the SHUTDOWN COMPLETE, the receiver of the OOTB
  *    packet must fill in the Verification Tag field of the outbound
  *    packet with the Verification Tag received in the SHUTDOWN ACK and
- *    set the T-bit in the Chunk Flags to indicate that no TCB was
- *    found. Otherwise,
+ *    set the T-bit in the Chunk Flags to indicate that the Verification
+ *    Tag is reflected.
  *
  * 8) The receiver should respond to the sender of the OOTB packet with
  *    an ABORT.  When sending the ABORT, the receiver of the OOTB packet
  *    MUST fill in the Verification Tag field of the outbound packet
  *    with the value found in the Verification Tag field of the OOTB
- *    packet and set the T-bit in the Chunk Flags to indicate that no
- *    TCB was found.  After sending this ABORT, the receiver of the OOTB
- *    packet shall discard the OOTB packet and take no further action.
+ *    packet and set the T-bit in the Chunk Flags to indicate that the
+ *    Verification Tag is reflected.  After sending this ABORT, the
+ *    receiver of the OOTB packet shall discard the OOTB packet and take
+ *    no further action.
  */
 sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
 				const struct sctp_association *asoc,
@@ -3090,13 +3099,15 @@
 /*
  * Handle an "Out of the blue" SHUTDOWN ACK.
  *
- * Section: 8.4 5)
+ * Section: 8.4 5, sctpimpguide 2.41.
+ *
  * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should
- *   respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE.
- *   When sending the SHUTDOWN COMPLETE, the receiver of the OOTB packet
- *   must fill in the Verification Tag field of the outbound packet with
- *   the Verification Tag received in the SHUTDOWN ACK and set the
- *   T-bit in the Chunk Flags to indicate that no TCB was found.
+ *    respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE.
+ *    When sending the SHUTDOWN COMPLETE, the receiver of the OOTB
+ *    packet must fill in the Verification Tag field of the outbound
+ *    packet with the Verification Tag received in the SHUTDOWN ACK and
+ *    set the T-bit in the Chunk Flags to indicate that the Verification
+ *    Tag is reflected.
  *
  * Inputs
  * (endpoint, asoc, type, arg, commands)
@@ -3128,6 +3139,10 @@
 			return SCTP_DISPOSITION_NOMEM;
 		}
 
+		/* Reflect vtag if T-Bit is set */
+		if (sctp_test_T_bit(shut))
+			packet->vtag = ntohl(chunk->sctp_hdr->vtag);
+
 		/* Set the skb to the belonging sock for accounting.  */
 		shut->skb->sk = ep->base.sk;
 
@@ -3591,7 +3606,6 @@
  *
  * 2) If the OOTB packet contains an ABORT chunk, the receiver MUST
  *    silently discard the OOTB packet and take no further action.
- *    Otherwise,
  *
  * Verification Tag: No verification necessary
  *
@@ -4961,6 +4975,11 @@
 			sctp_ootb_pkt_free(packet);
 			return NULL;
 		}
+
+		/* Reflect vtag if T-Bit is set */
+		if (sctp_test_T_bit(abort))
+			packet->vtag = ntohl(chunk->sctp_hdr->vtag);
+
 		/* Add specified error causes, i.e., payload, to the
 		 * end of the chunk.
 		 */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e8c2101..0b338ec 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -115,9 +115,17 @@
 	struct sock *sk = asoc->base.sk;
 	int amt = 0;
 
-	amt = sk->sk_sndbuf - asoc->sndbuf_used;
+	if (asoc->ep->sndbuf_policy) {
+		/* make sure that no association uses more than sk_sndbuf */
+		amt = sk->sk_sndbuf - asoc->sndbuf_used;
+	} else {
+		/* do socket level accounting */
+		amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
+	}
+
 	if (amt < 0)
 		amt = 0;
+
 	return amt;
 }
 
@@ -138,12 +146,21 @@
 	/* The sndbuf space is tracked per association.  */
 	sctp_association_hold(asoc);
 
+	skb_set_owner_w(chunk->skb, sk);
+
 	chunk->skb->destructor = sctp_wfree;
 	/* Save the chunk pointer in skb for sctp_wfree to use later.  */
 	*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
 
-	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
-	sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk);
+	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) +
+				sizeof(struct sk_buff) +
+				sizeof(struct sctp_chunk);
+
+	sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk) +
+				sizeof(struct sk_buff) +
+				sizeof(struct sctp_chunk);
+
+	atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
 }
 
 /* Verify that this is a valid address. */
@@ -3473,7 +3490,7 @@
 		return -EINVAL;
 
 	/* Values correspoinding to the specific association */
-	if (assocparams.sasoc_assoc_id != 0) {
+	if (asoc) {
 		assocparams.sasoc_asocmaxrxt = asoc->max_retrans;
 		assocparams.sasoc_peer_rwnd = asoc->peer.rwnd;
 		assocparams.sasoc_local_rwnd = asoc->a_rwnd;
@@ -4422,8 +4439,17 @@
 	chunk = *((struct sctp_chunk **)(skb->cb));
 	asoc = chunk->asoc;
 	sk = asoc->base.sk;
-	asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk);
-	sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk);
+	asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) +
+				sizeof(struct sk_buff) +
+				sizeof(struct sctp_chunk);
+
+	sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk) +
+				sizeof(struct sk_buff) +
+				sizeof(struct sctp_chunk);
+
+	atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
+
+	sock_wfree(skb);
 	__sctp_write_space(asoc);
 
 	sctp_association_put(asoc);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 89fa20c..7fc3184 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -110,6 +110,14 @@
 		.proc_handler	= &proc_dointvec
 	},
 	{
+		.ctl_name	= NET_SCTP_SNDBUF_POLICY,
+		.procname	= "sndbuf_policy",
+		.data		= &sctp_sndbuf_policy,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
 		.ctl_name	= NET_SCTP_PATH_MAX_RETRANS,
 		.procname	= "path_max_retrans",
 		.data		= &sctp_max_retrans_path,
diff --git a/net/socket.c b/net/socket.c
index 2cd4499..cec0cb3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -4,7 +4,7 @@
  * Version:	@(#)socket.c	1.1.93	18/02/95
  *
  * Authors:	Orest Zborowski, <obz@Kodak.COM>
- *		Ross Biro, <bir7@leland.Stanford.Edu>
+ *		Ross Biro
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *
  * Fixes:
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 4484931..67b9f035 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -46,9 +46,9 @@
 
 /**
  * xdr_encode_opaque_fixed - Encode fixed length opaque data
- * @p - pointer to current position in XDR buffer.
- * @ptr - pointer to data to encode (or NULL)
- * @nbytes - size of data.
+ * @p: pointer to current position in XDR buffer.
+ * @ptr: pointer to data to encode (or NULL)
+ * @nbytes: size of data.
  *
  * Copy the array of data of length nbytes at ptr to the XDR buffer
  * at position p, then align to the next 32-bit boundary by padding
@@ -76,9 +76,9 @@
 
 /**
  * xdr_encode_opaque - Encode variable length opaque data
- * @p - pointer to current position in XDR buffer.
- * @ptr - pointer to data to encode (or NULL)
- * @nbytes - size of data.
+ * @p: pointer to current position in XDR buffer.
+ * @ptr: pointer to data to encode (or NULL)
+ * @nbytes: size of data.
  *
  * Returns the updated current XDR buffer position
  */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index acc73fe..c478fc8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -85,7 +85,6 @@
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 956c17f..d6844ac 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -48,8 +48,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>	/* support for loadable modules */
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/mm.h>		/* verify_area(), etc. */
+#include <linux/slab.h>		/* kmalloc(), kfree() */
+#include <linux/mm.h>
 #include <linux/string.h>	/* inline mem*, str* functions */
 
 #include <asm/byteorder.h>	/* htons(), etc. */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8082807..55ed979 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1028,30 +1028,15 @@
 	return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC);
 }
 
-static void xfrm_dst_destroy(struct dst_entry *dst)
+void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
 {
-	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-
-	dst_release(xdst->route);
-
-	if (!dst->xfrm)
-		return;
-	xfrm_state_put(dst->xfrm);
-	dst->xfrm = NULL;
-}
-
-static void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
-			    int unregister)
-{
-	if (!unregister)
-		return;
-
 	while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
 		dst->dev = &loopback_dev;
 		dev_hold(&loopback_dev);
 		dev_put(dev);
 	}
 }
+EXPORT_SYMBOL(xfrm_dst_ifdown);
 
 static void xfrm_link_failure(struct sk_buff *skb)
 {
@@ -1262,10 +1247,6 @@
 			dst_ops->kmem_cachep = xfrm_dst_cache;
 		if (likely(dst_ops->check == NULL))
 			dst_ops->check = xfrm_dst_check;
-		if (likely(dst_ops->destroy == NULL))
-			dst_ops->destroy = xfrm_dst_destroy;
-		if (likely(dst_ops->ifdown == NULL))
-			dst_ops->ifdown = xfrm_dst_ifdown;
 		if (likely(dst_ops->negative_advice == NULL))
 			dst_ops->negative_advice = xfrm_negative_advice;
 		if (likely(dst_ops->link_failure == NULL))
@@ -1297,8 +1278,6 @@
 			xfrm_policy_afinfo[afinfo->family] = NULL;
 			dst_ops->kmem_cachep = NULL;
 			dst_ops->check = NULL;
-			dst_ops->destroy = NULL;
-			dst_ops->ifdown = NULL;
 			dst_ops->negative_advice = NULL;
 			dst_ops->link_failure = NULL;
 			dst_ops->get_mss = NULL;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1db59f1..d11747c 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -357,8 +357,9 @@
 
 	x = best;
 	if (!x && !error && !acquire_in_progress) {
-		x0 = afinfo->state_lookup(&tmpl->id.daddr, tmpl->id.spi, tmpl->id.proto);
-		if (x0 != NULL) {
+		if (tmpl->id.spi &&
+		    (x0 = afinfo->state_lookup(daddr, tmpl->id.spi,
+		                               tmpl->id.proto)) != NULL) {
 			xfrm_state_put(x0);
 			error = -EEXIST;
 			goto out;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 63661b0..5ddda2c 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -855,47 +855,44 @@
 	return 0;
 }
 
-static const int xfrm_msg_min[(XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)] = {
-	NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)),	/* NEW SA */
-	NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),	/* DEL SA */
-	NLMSG_LENGTH(sizeof(struct xfrm_usersa_id)),	/* GET SA */
-	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)),/* NEW POLICY */
-	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)),  /* DEL POLICY */
-	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id)),  /* GET POLICY */
-	NLMSG_LENGTH(sizeof(struct xfrm_userspi_info)),	/* ALLOC SPI */
-	NLMSG_LENGTH(sizeof(struct xfrm_user_acquire)),	/* ACQUIRE */
-	NLMSG_LENGTH(sizeof(struct xfrm_user_expire)),	/* EXPIRE */
-	NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)),/* UPD POLICY */
-	NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)),	/* UPD SA */
-	NLMSG_LENGTH(sizeof(struct xfrm_user_polexpire)), /* POLEXPIRE */
-	NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)),	/* FLUSH SA */
-	NLMSG_LENGTH(0),				/* FLUSH POLICY */
+#define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type))
+
+static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
+	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
+	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),
+	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id),
+	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
+	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
+	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
+	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info),
+	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire),
+	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire),
+	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info),
+	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info),
+	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire),
+	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush),
+	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0),
 };
 
+#undef XMSGSIZE
+
 static struct xfrm_link {
 	int (*doit)(struct sk_buff *, struct nlmsghdr *, void **);
 	int (*dump)(struct sk_buff *, struct netlink_callback *);
-} xfrm_dispatch[] = {
-	{	.doit	=	xfrm_add_sa, 		},
-	{	.doit	=	xfrm_del_sa, 		},
-	{
-		.doit	=	xfrm_get_sa,
-		.dump	=	xfrm_dump_sa,
-	},
-	{	.doit	=	xfrm_add_policy 	},
-	{	.doit	=	xfrm_get_policy 	},
-	{
-		.doit	=	xfrm_get_policy,
-		.dump	=	xfrm_dump_policy,
-	},
-	{	.doit	=	xfrm_alloc_userspi	},
-	{},
-	{},
-	{	.doit	=	xfrm_add_policy 	},
-	{	.doit	=	xfrm_add_sa, 		},
-	{},
-	{	.doit	=	xfrm_flush_sa		},
-	{	.doit	=	xfrm_flush_policy	},
+} xfrm_dispatch[XFRM_NR_MSGTYPES] = {
+	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
+	[XFRM_MSG_DELSA       - XFRM_MSG_BASE] = { .doit = xfrm_del_sa        },
+	[XFRM_MSG_GETSA       - XFRM_MSG_BASE] = { .doit = xfrm_get_sa,
+						   .dump = xfrm_dump_sa       },
+	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
+	[XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy    },
+	[XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
+						   .dump = xfrm_dump_policy   },
+	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
+	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
+	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = { .doit = xfrm_add_sa        },
+	[XFRM_MSG_FLUSHSA     - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa      },
+	[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy  },
 };
 
 static int xfrm_done(struct netlink_callback *cb)
@@ -931,7 +928,9 @@
 		return -1;
 	}
 
-	if ((type == 2 || type == 5) && (nlh->nlmsg_flags & NLM_F_DUMP)) {
+	if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
+	     type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) &&
+	    (nlh->nlmsg_flags & NLM_F_DUMP)) {
 		u32 rlen;
 
 		if (link->dump == NULL)
@@ -1009,18 +1008,26 @@
 
 static void xfrm_netlink_rcv(struct sock *sk, int len)
 {
+	unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
+
 	do {
 		struct sk_buff *skb;
 
 		down(&xfrm_cfg_sem);
 
-		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+		if (qlen > skb_queue_len(&sk->sk_receive_queue))
+			qlen = skb_queue_len(&sk->sk_receive_queue);
+
+		for (; qlen; qlen--) {
+			skb = skb_dequeue(&sk->sk_receive_queue);
 			if (xfrm_user_rcv_skb(skb)) {
 				if (skb->len)
 					skb_queue_head(&sk->sk_receive_queue,
 						       skb);
-				else
+				else {
 					kfree_skb(skb);
+					qlen--;
+				}
 				break;
 			}
 			kfree_skb(skb);
@@ -1028,7 +1035,7 @@
 
 		up(&xfrm_cfg_sem);
 
-	} while (xfrm_nl && xfrm_nl->sk_receive_queue.qlen);
+	} while (qlen);
 }
 
 static int build_expire(struct sk_buff *skb, struct xfrm_state *x, int hard)
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 090ffda..d3d2e53 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -67,8 +67,9 @@
 
 static struct sym_entry *table;
 static int size, cnt;
-static unsigned long long _stext, _etext, _sinittext, _einittext;
+static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
 static int all_symbols = 0;
+static char symbol_prefix_char = '\0';
 
 struct token {
 	unsigned char data[MAX_TOK_SIZE];
@@ -93,7 +94,7 @@
 static void
 usage(void)
 {
-	fprintf(stderr, "Usage: kallsyms [--all-symbols] < in.map > out.S\n");
+	fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
 	exit(1);
 }
 
@@ -112,6 +113,7 @@
 read_symbol(FILE *in, struct sym_entry *s)
 {
 	char str[500];
+	char *sym;
 	int rc;
 
 	rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str);
@@ -123,27 +125,36 @@
 		return -1;
 	}
 
+	sym = str;
+	/* skip prefix char */
+	if (symbol_prefix_char && str[0] == symbol_prefix_char)
+		sym++;
+
 	/* Ignore most absolute/undefined (?) symbols. */
-	if (strcmp(str, "_stext") == 0)
+	if (strcmp(sym, "_stext") == 0)
 		_stext = s->addr;
-	else if (strcmp(str, "_etext") == 0)
+	else if (strcmp(sym, "_etext") == 0)
 		_etext = s->addr;
-	else if (strcmp(str, "_sinittext") == 0)
+	else if (strcmp(sym, "_sinittext") == 0)
 		_sinittext = s->addr;
-	else if (strcmp(str, "_einittext") == 0)
+	else if (strcmp(sym, "_einittext") == 0)
 		_einittext = s->addr;
+	else if (strcmp(sym, "_sextratext") == 0)
+		_sextratext = s->addr;
+	else if (strcmp(sym, "_eextratext") == 0)
+		_eextratext = s->addr;
 	else if (toupper(s->type) == 'A')
 	{
 		/* Keep these useful absolute symbols */
-		if (strcmp(str, "__kernel_syscall_via_break") &&
-		    strcmp(str, "__kernel_syscall_via_epc") &&
-		    strcmp(str, "__kernel_sigtramp") &&
-		    strcmp(str, "__gp"))
+		if (strcmp(sym, "__kernel_syscall_via_break") &&
+		    strcmp(sym, "__kernel_syscall_via_epc") &&
+		    strcmp(sym, "__kernel_sigtramp") &&
+		    strcmp(sym, "__gp"))
 			return -1;
 
 	}
 	else if (toupper(s->type) == 'U' ||
-		 is_arm_mapping_symbol(str))
+		 is_arm_mapping_symbol(sym))
 		return -1;
 
 	/* include the type field in the symbol name, so that it gets
@@ -177,30 +188,37 @@
 		"_SDA2_BASE_",		/* ppc */
 		NULL };
 	int i;
+	int offset = 1;
+
+	/* skip prefix char */
+	if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
+		offset++;
 
 	/* if --all-symbols is not specified, then symbols outside the text
 	 * and inittext sections are discarded */
 	if (!all_symbols) {
 		if ((s->addr < _stext || s->addr > _etext)
-		    && (s->addr < _sinittext || s->addr > _einittext))
+		    && (s->addr < _sinittext || s->addr > _einittext)
+		    && (s->addr < _sextratext || s->addr > _eextratext))
 			return 0;
 		/* Corner case.  Discard any symbols with the same value as
-		 * _etext or _einittext, they can move between pass 1 and 2
-		 * when the kallsyms data is added.  If these symbols move then
-		 * they may get dropped in pass 2, which breaks the kallsyms
-		 * rules.
+		 * _etext _einittext or _eextratext; they can move between pass
+		 * 1 and 2 when the kallsyms data are added.  If these symbols
+		 * move then they may get dropped in pass 2, which breaks the
+		 * kallsyms rules.
 		 */
-		if ((s->addr == _etext && strcmp(s->sym + 1, "_etext")) ||
-		    (s->addr == _einittext && strcmp(s->sym + 1, "_einittext")))
+		if ((s->addr == _etext && strcmp(s->sym + offset, "_etext")) ||
+		    (s->addr == _einittext && strcmp(s->sym + offset, "_einittext")) ||
+		    (s->addr == _eextratext && strcmp(s->sym + offset, "_eextratext")))
 			return 0;
 	}
 
 	/* Exclude symbols which vary between passes. */
-	if (strstr(s->sym + 1, "_compiled."))
+	if (strstr(s->sym + offset, "_compiled."))
 		return 0;
 
 	for (i = 0; special_symbols[i]; i++)
-		if( strcmp(s->sym + 1, special_symbols[i]) == 0 )
+		if( strcmp(s->sym + offset, special_symbols[i]) == 0 )
 			return 0;
 
 	return 1;
@@ -225,9 +243,15 @@
 
 static void output_label(char *label)
 {
-	printf(".globl %s\n",label);
+	if (symbol_prefix_char)
+		printf(".globl %c%s\n", symbol_prefix_char, label);
+	else
+		printf(".globl %s\n", label);
 	printf("\tALGN\n");
-	printf("%s:\n",label);
+	if (symbol_prefix_char)
+		printf("%c%s:\n", symbol_prefix_char, label);
+	else
+		printf("%s:\n", label);
 }
 
 /* uncompress a compressed symbol. When this function is called, the best table
@@ -665,6 +689,13 @@
 
 	insert_real_symbols_in_table();
 
+	/* When valid symbol is not registered, exit to error */
+	if (good_head.left == good_head.right &&
+	    bad_head.left == bad_head.right) {
+		fprintf(stderr, "No valid symbol.\n");
+		exit(1);
+	}
+
 	optimize_result();
 }
 
@@ -672,9 +703,21 @@
 int
 main(int argc, char **argv)
 {
-	if (argc == 2 && strcmp(argv[1], "--all-symbols") == 0)
-		all_symbols = 1;
-	else if (argc != 1)
+	if (argc >= 2) {
+		int i;
+		for (i = 1; i < argc; i++) {
+			if(strcmp(argv[i], "--all-symbols") == 0)
+				all_symbols = 1;
+			else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
+				char *p = &argv[i][16];
+				/* skip quote */
+				if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
+					p++;
+				symbol_prefix_char = *p;
+			} else
+				usage();
+		}
+	} else if (argc != 1)
 		usage();
 
 	read_map(stdin);
@@ -683,4 +726,3 @@
 
 	return 0;
 }
-
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 5a5ddc4..09abb89 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -2,7 +2,7 @@
 # Kernel configuration targets
 # These targets are used from top-level makefile
 
-.PHONY: oldconfig xconfig gconfig menuconfig config silentoldconfig
+.PHONY: oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
 
 xconfig: $(obj)/qconf
 	$< arch/$(ARCH)/Kconfig
@@ -23,6 +23,13 @@
 silentoldconfig: $(obj)/conf
 	$< -s arch/$(ARCH)/Kconfig
 
+update-po-config: $(obj)/kxgettext
+	xgettext --default-domain=linux \
+          --add-comments --keyword=_ --keyword=N_ \
+          --files-from=scripts/kconfig/POTFILES.in \
+	-o scripts/kconfig/linux.pot
+	scripts/kconfig/kxgettext arch/$(ARCH)/Kconfig >> scripts/kconfig/linux.pot
+
 .PHONY: randconfig allyesconfig allnoconfig allmodconfig defconfig
 
 randconfig: $(obj)/conf
@@ -72,9 +79,10 @@
 #         Based on GTK which needs to be installed to compile it
 # object files used by all kconfig flavours
 
-hostprogs-y	:= conf mconf qconf gconf
+hostprogs-y	:= conf mconf qconf gconf kxgettext
 conf-objs	:= conf.o  zconf.tab.o
 mconf-objs	:= mconf.o zconf.tab.o
+kxgettext-objs	:= kxgettext.o zconf.tab.o
 
 ifeq ($(MAKECMDGOALS),xconfig)
 	qconf-target := 1
@@ -107,7 +115,7 @@
 HOSTCFLAGS_gconf.o	= `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \
                           -D LKC_DIRECT_LINK
 
-$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o: $(obj)/zconf.tab.h
+$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o $(obj)/kxgettext: $(obj)/zconf.tab.h
 
 $(obj)/zconf.tab.h: $(src)/zconf.tab.h_shipped
 $(obj)/zconf.tab.c: $(src)/zconf.tab.c_shipped
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
new file mode 100644
index 0000000..cc94e46
--- /dev/null
+++ b/scripts/kconfig/POTFILES.in
@@ -0,0 +1,5 @@
+scripts/kconfig/mconf.c
+scripts/kconfig/conf.c
+scripts/kconfig/confdata.c
+scripts/kconfig/gconf.c
+scripts/kconfig/qconf.cc
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index a494d1a..70e7264 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -34,7 +34,7 @@
 static signed char line[128];
 static struct menu *rootEntry;
 
-static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
+static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
 
 static void strip(signed char *str)
 {
@@ -56,9 +56,9 @@
 static void check_stdin(void)
 {
 	if (!valid_stdin && input_mode == ask_silent) {
-		printf("aborted!\n\n");
-		printf("Console input/output is redirected. ");
-		printf("Run 'make oldconfig' to update configuration.\n\n");
+		printf(_("aborted!\n\n"));
+		printf(_("Console input/output is redirected. "));
+		printf(_("Run 'make oldconfig' to update configuration.\n\n"));
 		exit(1);
 	}
 }
@@ -470,7 +470,7 @@
 	if (sym) {
 		if (sym_is_changable(sym) && !sym_has_value(sym)) {
 			if (!conf_cnt++)
-				printf("*\n* Restart config...\n*\n");
+				printf(_("*\n* Restart config...\n*\n"));
 			rootEntry = menu_get_parent_menu(menu);
 			conf(rootEntry);
 		}
@@ -504,7 +504,7 @@
 			input_mode = set_default;
 			defconfig_file = av[i++];
 			if (!defconfig_file) {
-				printf("%s: No default config file specified\n",
+				printf(_("%s: No default config file specified\n"),
 					av[0]);
 				exit(1);
 			}
@@ -530,7 +530,7 @@
 	}
   	name = av[i];
 	if (!name) {
-		printf("%s: Kconfig file missing\n", av[0]);
+		printf(_("%s: Kconfig file missing\n"), av[0]);
 	}
 	conf_parse(name);
 	//zconfdump(stdout);
@@ -547,12 +547,12 @@
 		break;
 	case ask_silent:
 		if (stat(".config", &tmpstat)) {
-			printf("***\n"
+			printf(_("***\n"
 				"*** You have not yet configured your kernel!\n"
 				"***\n"
 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
 				"*** \"make menuconfig\" or \"make xconfig\").\n"
-				"***\n");
+				"***\n"));
 			exit(1);
 		}
 	case ask_all:
@@ -576,7 +576,7 @@
 		check_conf(&rootmenu);
 	} while (conf_cnt);
 	if (conf_write(NULL)) {
-		fprintf(stderr, "\n*** Error during writing of the kernel configuration.\n\n");
+		fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
 		return 1;
 	}
 	return 0;
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1e82ae3..2755c45 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -88,9 +88,9 @@
 			name = conf_expand_value(name);
 			in = zconf_fopen(name);
 			if (in) {
-				printf("#\n"
-				       "# using defaults found in %s\n"
-				       "#\n", name);
+				printf(_("#\n"
+				         "# using defaults found in %s\n"
+				         "#\n"), name);
 				break;
 			}
 		}
@@ -312,11 +312,11 @@
 	if (env && *env)
 		use_timestamp = 0;
 
-	fprintf(out, "#\n"
-		     "# Automatically generated make config: don't edit\n"
-		     "# Linux kernel version: %s\n"
-		     "%s%s"
-		     "#\n",
+	fprintf(out, _("#\n"
+		       "# Automatically generated make config: don't edit\n"
+		       "# Linux kernel version: %s\n"
+		       "%s%s"
+		       "#\n"),
 		     sym_get_string_value(sym),
 		     use_timestamp ? "# " : "",
 		     use_timestamp ? ctime(&now) : "");
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 6fdbe6e..ad6b120 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -41,7 +41,7 @@
 static gboolean config_changed = FALSE;
 
 static char nohelp_text[] =
-    "Sorry, no help available for this option yet.\n";
+    N_("Sorry, no help available for this option yet.\n");
 
 GtkWidget *main_wnd = NULL;
 GtkWidget *tree1_w = NULL;	// left  frame
@@ -193,7 +193,7 @@
 
 	xml = glade_xml_new(glade_file, "window1", NULL);
 	if (!xml)
-		g_error("GUI loading failed !\n");
+		g_error(_("GUI loading failed !\n"));
 	glade_xml_signal_autoconnect(xml);
 
 	main_wnd = glade_xml_get_widget(xml, "window1");
@@ -275,7 +275,7 @@
 					  /*"style", PANGO_STYLE_OBLIQUE, */
 					  NULL);
 
-	sprintf(title, "Linux Kernel v%s Configuration",
+	sprintf(title, _("Linux Kernel v%s Configuration"),
 		getenv("KERNELRELEASE"));
 	gtk_window_set_title(GTK_WINDOW(main_wnd), title);
 
@@ -325,7 +325,7 @@
 	
 	column = gtk_tree_view_column_new();
 	gtk_tree_view_append_column(view, column);
-	gtk_tree_view_column_set_title(column, "Options");
+	gtk_tree_view_column_set_title(column, _("Options"));
 
 	renderer = gtk_cell_renderer_toggle_new();
 	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
@@ -370,7 +370,7 @@
 
 	column = gtk_tree_view_column_new();
 	gtk_tree_view_append_column(view, column);
-	gtk_tree_view_column_set_title(column, "Options");
+	gtk_tree_view_column_set_title(column, _("Options"));
 
 	renderer = gtk_cell_renderer_pixbuf_new();
 	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
@@ -401,7 +401,7 @@
 
 	renderer = gtk_cell_renderer_text_new();
 	gtk_tree_view_insert_column_with_attributes(view, -1,
-						    "Name", renderer,
+						    _("Name"), renderer,
 						    "text", COL_NAME,
 						    "foreground-gdk",
 						    COL_COLOR, NULL);
@@ -425,7 +425,7 @@
 						    COL_COLOR, NULL);
 	renderer = gtk_cell_renderer_text_new();
 	gtk_tree_view_insert_column_with_attributes(view, -1,
-						    "Value", renderer,
+						    _("Value"), renderer,
 						    "text", COL_VALUE,
 						    "editable",
 						    COL_EDIT,
@@ -466,15 +466,15 @@
 	GtkTextIter start, end;
 	const char *prompt = menu_get_prompt(menu);
 	gchar *name;
-	const char *help = nohelp_text;
+	const char *help = _(nohelp_text);
 
 	if (!menu->sym)
 		help = "";
 	else if (menu->sym->help)
-		help = menu->sym->help;
+		help = _(menu->sym->help);
 
 	if (menu->sym && menu->sym->name)
-		name = g_strdup_printf(menu->sym->name);
+		name = g_strdup_printf(_(menu->sym->name));
 	else
 		name = g_strdup("");
 
@@ -530,7 +530,7 @@
 	if (config_changed == FALSE)
 		return FALSE;
 
-	dialog = gtk_dialog_new_with_buttons("Warning !",
+	dialog = gtk_dialog_new_with_buttons(_("Warning !"),
 					     GTK_WINDOW(main_wnd),
 					     (GtkDialogFlags)
 					     (GTK_DIALOG_MODAL |
@@ -544,7 +544,7 @@
 	gtk_dialog_set_default_response(GTK_DIALOG(dialog),
 					GTK_RESPONSE_CANCEL);
 
-	label = gtk_label_new("\nSave configuration ?\n");
+	label = gtk_label_new(_("\nSave configuration ?\n"));
 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
 	gtk_widget_show(label);
 
@@ -604,7 +604,7 @@
 					     (user_data));
 
 	if (conf_read(fn))
-		text_insert_msg("Error", "Unable to load configuration !");
+		text_insert_msg(_("Error"), _("Unable to load configuration !"));
 	else
 		display_tree(&rootmenu);
 }
@@ -613,7 +613,7 @@
 {
 	GtkWidget *fs;
 
-	fs = gtk_file_selection_new("Load file...");
+	fs = gtk_file_selection_new(_("Load file..."));
 	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
 			 "clicked",
 			 G_CALLBACK(load_filename), (gpointer) fs);
@@ -632,7 +632,7 @@
 void on_save1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
 	if (conf_write(NULL))
-		text_insert_msg("Error", "Unable to save configuration !");
+		text_insert_msg(_("Error"), _("Unable to save configuration !"));
 
 	config_changed = FALSE;
 }
@@ -647,7 +647,7 @@
 					     (user_data));
 
 	if (conf_write(fn))
-		text_insert_msg("Error", "Unable to save configuration !");
+		text_insert_msg(_("Error"), _("Unable to save configuration !"));
 
 	gtk_widget_destroy(GTK_WIDGET(user_data));
 }
@@ -656,7 +656,7 @@
 {
 	GtkWidget *fs;
 
-	fs = gtk_file_selection_new("Save file as...");
+	fs = gtk_file_selection_new(_("Save file as..."));
 	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
 			 "clicked",
 			 G_CALLBACK(store_filename), (gpointer) fs);
@@ -740,7 +740,7 @@
 void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
 	GtkWidget *dialog;
-	const gchar *intro_text =
+	const gchar *intro_text = _(
 	    "Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
 	    "for Linux.\n"
 	    "For each option, a blank box indicates the feature is disabled, a\n"
@@ -756,7 +756,7 @@
 	    "option.\n"
 	    "\n"
 	    "Toggling Show Debug Info under the Options menu will show \n"
-	    "the dependencies, which you can then match by examining other options.";
+	    "the dependencies, which you can then match by examining other options.");
 
 	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
 					GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -773,8 +773,8 @@
 {
 	GtkWidget *dialog;
 	const gchar *about_text =
-	    "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
-	    "Based on the source code from Roman Zippel.\n";
+	    _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+	      "Based on the source code from Roman Zippel.\n");
 
 	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
 					GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -791,9 +791,9 @@
 {
 	GtkWidget *dialog;
 	const gchar *license_text =
-	    "gkc is released under the terms of the GNU GPL v2.\n"
-	    "For more information, please see the source code or\n"
-	    "visit http://www.fsf.org/licenses/licenses.html\n";
+	    _("gkc is released under the terms of the GNU GPL v2.\n"
+	      "For more information, please see the source code or\n"
+	      "visit http://www.fsf.org/licenses/licenses.html\n");
 
 	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
 					GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -1579,6 +1579,10 @@
 	kconfig_load();
 #endif
 
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset(PACKAGE, "UTF-8");
+	textdomain(PACKAGE);
+
 	/* GTK stuffs */
 	gtk_set_locale();
 	gtk_init(&ac, &av);
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
new file mode 100644
index 0000000..1c88d7c
--- /dev/null
+++ b/scripts/kconfig/kxgettext.c
@@ -0,0 +1,221 @@
+/*
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
+ *
+ * Released under the terms of the GNU GPL v2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static char *escape(const char* text, char *bf, int len)
+{
+	char *bfp = bf;
+	int multiline = strchr(text, '\n') != NULL;
+
+	*bfp++ = '"';
+	--len;
+
+	if (multiline) {
+		*bfp++ = '"';
+		*bfp++ = '\n';
+		*bfp++ = '"';
+		len -= 3;
+	}
+
+	while (*text != '\0' && len > 1) {
+		if (*text == '"')
+			*bfp++ = '\\';
+		else if (*text == '\n') {
+			*bfp++ = '\\';
+			*bfp++ = 'n';
+			*bfp++ = '"';
+			*bfp++ = '\n';
+			*bfp++ = '"';
+			len -= 5;
+			++text;
+			goto next;
+		}
+		*bfp++ = *text++;
+next:
+		--len;
+	}
+
+	if (multiline)
+		bfp -= 3;
+
+	*bfp++ = '"';
+	*bfp = '\0';
+
+	return bf;
+}
+
+struct file_line {
+	struct file_line *next;
+	char*		 file;
+	int		 lineno;
+};
+
+static struct file_line *file_line__new(char *file, int lineno)
+{
+	struct file_line *self = malloc(sizeof(*self));
+
+	if (self == NULL)
+		goto out;
+
+	self->file   = file;
+	self->lineno = lineno;
+	self->next   = NULL;
+out:
+	return self;
+}
+
+struct message {
+	const char	 *msg;
+	const char	 *option;
+	struct message	 *next;
+	struct file_line *files;
+};
+
+static struct message *message__list;
+
+static struct message *message__new(const char *msg, char *option, char *file, int lineno)
+{
+	struct message *self = malloc(sizeof(*self));
+
+	if (self == NULL)
+		goto out;
+
+	self->files = file_line__new(file, lineno);
+	if (self->files == NULL)
+		goto out_fail;
+
+	self->msg = strdup(msg);
+	if (self->msg == NULL)
+		goto out_fail_msg;
+
+	self->option = option;
+	self->next = NULL;
+out:
+	return self;
+out_fail_msg:
+	free(self->files);
+out_fail:
+	free(self);
+	self = NULL;
+	goto out;
+}
+
+static struct message *mesage__find(const char *msg)
+{
+	struct message *m = message__list;
+
+	while (m != NULL) {
+		if (strcmp(m->msg, msg) == 0)
+			break;
+		m = m->next;
+	}
+
+	return m;
+}
+
+static int message__add_file_line(struct message *self, char *file, int lineno)
+{
+	int rc = -1;
+	struct file_line *fl = file_line__new(file, lineno);
+
+	if (fl == NULL)
+		goto out;
+
+	fl->next    = self->files;
+	self->files = fl;
+	rc = 0;
+out:
+	return rc;
+}
+
+static int message__add(const char *msg, char *option, char *file, int lineno)
+{
+	int rc = 0;
+	char bf[16384];
+	char *escaped = escape(msg, bf, sizeof(bf));
+	struct message *m = mesage__find(escaped);
+
+	if (m != NULL)
+		rc = message__add_file_line(m, file, lineno);
+	else {
+		m = message__new(escaped, option, file, lineno);
+
+		if (m != NULL) {
+			m->next	      = message__list;
+			message__list = m;
+		} else
+			rc = -1;
+	}
+	return rc;
+}
+
+void menu_build_message_list(struct menu *menu)
+{
+	struct menu *child;
+
+	message__add(menu_get_prompt(menu), NULL,
+		     menu->file == NULL ? "Root Menu" : menu->file->name,
+		     menu->lineno);
+
+	if (menu->sym != NULL && menu->sym->help != NULL)
+		message__add(menu->sym->help, menu->sym->name,
+			     menu->file == NULL ? "Root Menu" : menu->file->name,
+			     menu->lineno);
+
+	for (child = menu->list; child != NULL; child = child->next)
+		if (child->prompt != NULL)
+			menu_build_message_list(child);
+}
+
+static void message__print_file_lineno(struct message *self)
+{
+	struct file_line *fl = self->files;
+
+	printf("\n#: %s:%d", fl->file, fl->lineno);
+	fl = fl->next;
+
+	while (fl != NULL) {
+		printf(", %s:%d", fl->file, fl->lineno);
+		fl = fl->next;
+	}
+
+	if (self->option != NULL)
+		printf(", %s:00000", self->option);
+
+	putchar('\n');
+}
+
+static void message__print_gettext_msgid_msgstr(struct message *self)
+{
+	message__print_file_lineno(self);
+
+	printf("msgid %s\n"
+	       "msgstr \"\"\n", self->msg);
+}
+
+void menu__xgettext(void)
+{
+	struct message *m = message__list;
+
+	while (m != NULL) {
+		message__print_gettext_msgid_msgstr(m);
+		m = m->next;
+	}
+}
+
+int main(int ac, char **av)
+{
+	conf_parse(av[1]);
+
+	menu_build_message_list(menu_get_root_menu(NULL));
+	menu__xgettext();
+	return 0;
+}
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index b8a67fc..8b84c42 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -8,6 +8,8 @@
 
 #include "expr.h"
 
+#include <libintl.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -23,6 +25,12 @@
 
 #define SRCTREE "srctree"
 
+#define PACKAGE "linux"
+#define LOCALEDIR "/usr/share/locale"
+
+#define _(text) gettext(text)
+#define N_(text) (text)
+
 int zconfparse(void);
 void zconfdump(FILE *out);
 
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 730d316..e5db10c 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -4,6 +4,8 @@
  *
  * Introduced single menu mode (show all sub-menus in one large tree).
  * 2002-11-06 Petr Baudis <pasky@ucw.cz>
+ *
+ * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  */
 
 #include <sys/ioctl.h>
@@ -23,7 +25,7 @@
 #include "lkc.h"
 
 static char menu_backtitle[128];
-static const char mconf_readme[] =
+static const char mconf_readme[] = N_(
 "Overview\n"
 "--------\n"
 "Some kernel features may be built directly into the kernel.\n"
@@ -156,39 +158,39 @@
 "\n"
 "Note that this mode can eventually be a little more CPU expensive\n"
 "(especially with a larger number of unrolled categories) than the\n"
-"default mode.\n",
-menu_instructions[] =
+"default mode.\n"),
+menu_instructions[] = N_(
 	"Arrow keys navigate the menu.  "
 	"<Enter> selects submenus --->.  "
 	"Highlighted letters are hotkeys.  "
 	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  "
 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
-	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable",
-radiolist_instructions[] =
+	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable"),
+radiolist_instructions[] = N_(
 	"Use the arrow keys to navigate this window or "
 	"press the hotkey of the item you wish to select "
 	"followed by the <SPACE BAR>. "
-	"Press <?> for additional information about this option.",
-inputbox_instructions_int[] =
+	"Press <?> for additional information about this option."),
+inputbox_instructions_int[] = N_(
 	"Please enter a decimal value. "
 	"Fractions will not be accepted.  "
-	"Use the <TAB> key to move from the input field to the buttons below it.",
-inputbox_instructions_hex[] =
+	"Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_hex[] = N_(
 	"Please enter a hexadecimal value. "
-	"Use the <TAB> key to move from the input field to the buttons below it.",
-inputbox_instructions_string[] =
+	"Use the <TAB> key to move from the input field to the buttons below it."),
+inputbox_instructions_string[] = N_(
 	"Please enter a string value. "
-	"Use the <TAB> key to move from the input field to the buttons below it.",
-setmod_text[] =
+	"Use the <TAB> key to move from the input field to the buttons below it."),
+setmod_text[] = N_(
 	"This feature depends on another which has been configured as a module.\n"
-	"As a result, this feature will be built as a module.",
-nohelp_text[] =
-	"There is no help available for this kernel option.\n",
-load_config_text[] =
+	"As a result, this feature will be built as a module."),
+nohelp_text[] = N_(
+	"There is no help available for this kernel option.\n"),
+load_config_text[] = N_(
 	"Enter the name of the configuration file you wish to load.  "
 	"Accept the name shown to restore the configuration you "
-	"last retrieved.  Leave blank to abort.",
-load_config_help[] =
+	"last retrieved.  Leave blank to abort."),
+load_config_help[] = N_(
 	"\n"
 	"For various reasons, one may wish to keep several different kernel\n"
 	"configurations available on a single machine.\n"
@@ -198,11 +200,11 @@
 	"to modify that configuration.\n"
 	"\n"
 	"If you are uncertain, then you have probably never used alternate\n"
-	"configuration files.  You should therefor leave this blank to abort.\n",
-save_config_text[] =
+	"configuration files.  You should therefor leave this blank to abort.\n"),
+save_config_text[] = N_(
 	"Enter a filename to which this configuration should be saved "
-	"as an alternate.  Leave blank to abort.",
-save_config_help[] =
+	"as an alternate.  Leave blank to abort."),
+save_config_help[] = N_(
 	"\n"
 	"For various reasons, one may wish to keep different kernel\n"
 	"configurations available on a single machine.\n"
@@ -212,8 +214,8 @@
 	"configuration options you have selected at that time.\n"
 	"\n"
 	"If you are uncertain what all this means then you should probably\n"
-	"leave this blank.\n",
-search_help[] =
+	"leave this blank.\n"),
+search_help[] = N_(
 	"\n"
 	"Search for CONFIG_ symbols and display their relations.\n"
 	"Example: search for \"^FOO\"\n"
@@ -250,7 +252,7 @@
 	"Examples: USB	=> find all CONFIG_ symbols containing USB\n"
 	"          ^USB => find all CONFIG_ symbols starting with USB\n"
 	"          USB$ => find all CONFIG_ symbols ending with USB\n"
-	"\n";
+	"\n");
 
 static signed char buf[4096], *bufptr = buf;
 static signed char input_buf[4096];
@@ -305,8 +307,8 @@
 	}
 
 	if (rows < 19 || cols < 80) {
-		fprintf(stderr, "Your display is too small to run Menuconfig!\n");
-		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
+		fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
+		fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
 		exit(1);
 	}
 
@@ -526,9 +528,9 @@
 again:
 	cprint_init();
 	cprint("--title");
-	cprint("Search Configuration Parameter");
+	cprint(_("Search Configuration Parameter"));
 	cprint("--inputbox");
-	cprint("Enter Keyword");
+	cprint(_("Enter Keyword"));
 	cprint("10");
 	cprint("75");
 	cprint("");
@@ -539,7 +541,7 @@
 	case 0:
 		break;
 	case 1:
-		show_helptext("Search Configuration", search_help);
+		show_helptext(_("Search Configuration"), search_help);
 		goto again;
 	default:
 		return;
@@ -548,7 +550,7 @@
 	sym_arr = sym_re_search(input_buf);
 	res = get_relations_str(sym_arr);
 	free(sym_arr);
-	show_textbox("Search Results", str_get(&res), 0, 0);
+	show_textbox(_("Search Results"), str_get(&res), 0, 0);
 	str_free(&res);
 }
 
@@ -721,9 +723,9 @@
 	while (1) {
 		cprint_init();
 		cprint("--title");
-		cprint("%s", prompt ? prompt : "Main Menu");
+		cprint("%s", prompt ? prompt : _("Main Menu"));
 		cprint("--menu");
-		cprint(menu_instructions);
+		cprint(_(menu_instructions));
 		cprint("%d", rows);
 		cprint("%d", cols);
 		cprint("%d", rows - 10);
@@ -736,9 +738,9 @@
 			cprint(":");
 			cprint("--- ");
 			cprint("L");
-			cprint("    Load an Alternate Configuration File");
+			cprint(_("    Load an Alternate Configuration File"));
 			cprint("S");
-			cprint("    Save Configuration to an Alternate File");
+			cprint(_("    Save Configuration to an Alternate File"));
 		}
 		stat = exec_conf();
 		if (stat < 0)
@@ -793,7 +795,7 @@
 			if (sym)
 				show_help(submenu);
 			else
-				show_helptext("README", mconf_readme);
+				show_helptext("README", _(mconf_readme));
 			break;
 		case 3:
 			if (type == 't') {
@@ -849,7 +851,7 @@
 	{
 		if (sym->name) {
 			str_printf(&help, "CONFIG_%s:\n\n", sym->name);
-			str_append(&help, sym->help);
+			str_append(&help, _(sym->help));
 			str_append(&help, "\n");
 		}
 	} else {
@@ -886,9 +888,9 @@
 	while (1) {
 		cprint_init();
 		cprint("--title");
-		cprint("%s", prompt ? prompt : "Main Menu");
+		cprint("%s", prompt ? prompt : _("Main Menu"));
 		cprint("--radiolist");
-		cprint(radiolist_instructions);
+		cprint(_(radiolist_instructions));
 		cprint("15");
 		cprint("70");
 		cprint("6");
@@ -935,17 +937,17 @@
 	while (1) {
 		cprint_init();
 		cprint("--title");
-		cprint("%s", prompt ? prompt : "Main Menu");
+		cprint("%s", prompt ? prompt : _("Main Menu"));
 		cprint("--inputbox");
 		switch (sym_get_type(menu->sym)) {
 		case S_INT:
-			cprint(inputbox_instructions_int);
+			cprint(_(inputbox_instructions_int));
 			break;
 		case S_HEX:
-			cprint(inputbox_instructions_hex);
+			cprint(_(inputbox_instructions_hex));
 			break;
 		case S_STRING:
-			cprint(inputbox_instructions_string);
+			cprint(_(inputbox_instructions_string));
 			break;
 		default:
 			/* panic? */;
@@ -958,7 +960,7 @@
 		case 0:
 			if (sym_set_string_value(menu->sym, input_buf))
 				return;
-			show_textbox(NULL, "You have made an invalid entry.", 5, 43);
+			show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
 			break;
 		case 1:
 			show_help(menu);
@@ -987,10 +989,10 @@
 				return;
 			if (!conf_read(input_buf))
 				return;
-			show_textbox(NULL, "File does not exist!", 5, 38);
+			show_textbox(NULL, _("File does not exist!"), 5, 38);
 			break;
 		case 1:
-			show_helptext("Load Alternate Configuration", load_config_help);
+			show_helptext(_("Load Alternate Configuration"), load_config_help);
 			break;
 		case 255:
 			return;
@@ -1016,10 +1018,10 @@
 				return;
 			if (!conf_write(input_buf))
 				return;
-			show_textbox(NULL, "Can't create file!  Probably a nonexistent directory.", 5, 60);
+			show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60);
 			break;
 		case 1:
-			show_helptext("Save Alternate Configuration", save_config_help);
+			show_helptext(_("Save Alternate Configuration"), save_config_help);
 			break;
 		case 255:
 			return;
@@ -1040,12 +1042,16 @@
 	char *mode;
 	int stat;
 
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+
 	conf_parse(av[1]);
 	conf_read(NULL);
 
 	sym = sym_lookup("KERNELRELEASE", 0);
 	sym_calc_value(sym);
-	sprintf(menu_backtitle, "Linux Kernel v%s Configuration",
+	sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"),
 		sym_get_string_value(sym));
 
 	mode = getenv("MENUCONFIG_MODE");
@@ -1062,7 +1068,7 @@
 	do {
 		cprint_init();
 		cprint("--yesno");
-		cprint("Do you wish to save your new kernel configuration?");
+		cprint(_("Do you wish to save your new kernel configuration?"));
 		cprint("5");
 		cprint("60");
 		stat = exec_conf();
@@ -1070,20 +1076,20 @@
 
 	if (stat == 0) {
 		if (conf_write(NULL)) {
-			fprintf(stderr, "\n\n"
+			fprintf(stderr, _("\n\n"
 				"Error during writing of the kernel configuration.\n"
 				"Your kernel configuration changes were NOT saved."
-				"\n\n");
+				"\n\n"));
 			return 1;
 		}
-		printf("\n\n"
+		printf(_("\n\n"
 			"*** End of Linux kernel configuration.\n"
 			"*** Execute 'make' to build the kernel or try 'make help'."
-			"\n\n");
+			"\n\n"));
 	} else {
-		fprintf(stderr, "\n\n"
+		fprintf(stderr, _("\n\n"
 			"Your kernel configuration changes were NOT saved."
-			"\n\n");
+			"\n\n"));
 	}
 
 	return 0;
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 0c13156..8c59b21 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -365,9 +365,9 @@
 const char *menu_get_prompt(struct menu *menu)
 {
 	if (menu->prompt)
-		return menu->prompt->text;
+		return _(menu->prompt->text);
 	else if (menu->sym)
-		return menu->sym->name;
+		return _(menu->sym->name);
 	return NULL;
 }
 
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 0cdbf9d..4590cd3 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -26,8 +26,23 @@
 #include "qconf.moc"
 #include "images.c"
 
+#ifdef _
+# undef _
+# define _ qgettext
+#endif
+
 static QApplication *configApp;
 
+static inline QString qgettext(const char* str)
+{
+  return QString::fromLocal8Bit(gettext(str));
+}
+
+static inline QString qgettext(const QString& str)
+{
+  return QString::fromLocal8Bit(gettext(str.latin1()));
+}
+
 ConfigSettings::ConfigSettings()
 	: showAll(false), showName(false), showRange(false), showData(false)
 {
@@ -177,7 +192,7 @@
 
 	sym = menu->sym;
 	prop = menu->prompt;
-	prompt = menu_get_prompt(menu);
+	prompt = QString::fromLocal8Bit(menu_get_prompt(menu));
 
 	if (prop) switch (prop->type) {
 	case P_MENU:
@@ -203,7 +218,7 @@
 	if (!sym)
 		goto set_prompt;
 
-	setText(nameColIdx, sym->name);
+	setText(nameColIdx, QString::fromLocal8Bit(sym->name));
 
 	type = sym_get_type(sym);
 	switch (type) {
@@ -213,9 +228,9 @@
 
 		if (!sym_is_changable(sym) && !list->showAll) {
 			setPixmap(promptColIdx, 0);
-			setText(noColIdx, 0);
-			setText(modColIdx, 0);
-			setText(yesColIdx, 0);
+			setText(noColIdx, QString::null);
+			setText(modColIdx, QString::null);
+			setText(yesColIdx, QString::null);
 			break;
 		}
 		expr = sym_get_tristate_value(sym);
@@ -257,6 +272,7 @@
 		const char* data;
 
 		data = sym_get_string_value(sym);
+
 #if QT_VERSION >= 300
 		int i = list->mapIdx(dataColIdx);
 		if (i >= 0)
@@ -264,9 +280,9 @@
 #endif
 		setText(dataColIdx, data);
 		if (type == S_STRING)
-			prompt.sprintf("%s: %s", prompt.latin1(), data);
+			prompt = QString("%1: %2").arg(prompt).arg(data);
 		else
-			prompt.sprintf("(%s) %s", data, prompt.latin1());
+			prompt = QString("(%2) %1").arg(prompt).arg(data);
 		break;
 	}
 	if (!sym_has_value(sym) && visible)
@@ -343,9 +359,9 @@
 {
 	item = i;
 	if (sym_get_string_value(item->menu->sym))
-		setText(sym_get_string_value(item->menu->sym));
+		setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym)));
 	else
-		setText(0);
+		setText(QString::null);
 	Parent::show();
 	setFocus();
 }
@@ -961,7 +977,7 @@
 	delete configSettings;
 }
 
-static QString print_filter(const char *str)
+static QString print_filter(const QString &str)
 {
 	QRegExp re("[<>&\"\\n]");
 	QString res = str;
@@ -994,7 +1010,7 @@
 
 static void expr_print_help(void *data, const char *str)
 {
-	((QString*)data)->append(print_filter(str));
+	reinterpret_cast<QString*>(data)->append(print_filter(str));
 }
 
 /*
@@ -1009,7 +1025,7 @@
 	if (item)
 		menu = ((ConfigItem*)item)->menu;
 	if (!menu) {
-		helpText->setText(NULL);
+		helpText->setText(QString::null);
 		return;
 	}
 
@@ -1019,16 +1035,16 @@
 	if (sym) {
 		if (menu->prompt) {
 			head += "<big><b>";
-			head += print_filter(menu->prompt->text);
+			head += print_filter(_(menu->prompt->text));
 			head += "</b></big>";
 			if (sym->name) {
 				head += " (";
-				head += print_filter(sym->name);
+				head += print_filter(_(sym->name));
 				head += ")";
 			}
 		} else if (sym->name) {
 			head += "<big><b>";
-			head += print_filter(sym->name);
+			head += print_filter(_(sym->name));
 			head += "</b></big>";
 		}
 		head += "<br><br>";
@@ -1049,7 +1065,7 @@
 				case P_PROMPT:
 				case P_MENU:
 					debug += "prompt: ";
-					debug += print_filter(prop->text);
+					debug += print_filter(_(prop->text));
 					debug += "<br>";
 					break;
 				case P_DEFAULT:
@@ -1088,10 +1104,10 @@
 			debug += "<br>";
 		}
 
-		help = print_filter(sym->help);
+		help = print_filter(_(sym->help));
 	} else if (menu->prompt) {
 		head += "<big><b>";
-		head += print_filter(menu->prompt->text);
+		head += print_filter(_(menu->prompt->text));
 		head += "</b></big><br><br>";
 		if (showDebug) {
 			if (menu->prompt->visible.expr) {
@@ -1111,7 +1127,7 @@
 	QString s = QFileDialog::getOpenFileName(".config", NULL, this);
 	if (s.isNull())
 		return;
-	if (conf_read(s.latin1()))
+	if (conf_read(QFile::encodeName(s)))
 		QMessageBox::information(this, "qconf", "Unable to load configuration!");
 	ConfigView::updateListAll();
 }
@@ -1127,7 +1143,7 @@
 	QString s = QFileDialog::getSaveFileName(".config", NULL, this);
 	if (s.isNull())
 		return;
-	if (conf_write(s.latin1()))
+	if (conf_write(QFile::encodeName(s)))
 		QMessageBox::information(this, "qconf", "Unable to save configuration!");
 }
 
@@ -1372,6 +1388,9 @@
 	ConfigMainWindow* v;
 	const char *name;
 
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+
 #ifndef LKC_DIRECT_LINK
 	kconfig_load();
 #endif
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 8b1dab6..0835dc2 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -553,15 +553,20 @@
     # print out each section
     $lineprefix="   ";
     foreach $section (@{$args{'sectionlist'}}) {
-	print "<refsect1>\n <title>$section</title>\n <para>\n";
+	print "<refsect1>\n";
+	print "<title>$section</title>\n";
 	if ($section =~ m/EXAMPLE/i) {
-	    print "<example><para>\n";
+	    print "<informalexample><programlisting>\n";
+	} else {
+	    print "<para>\n";
 	}
 	output_highlight($args{'sections'}{$section});
 	if ($section =~ m/EXAMPLE/i) {
-	    print "</para></example>\n";
+	    print "</programlisting></informalexample>\n";
+	} else {
+	    print "</para>\n";
 	}
-	print " </para>\n</refsect1>\n";
+	print "</refsect1>\n";
     }
 }
 
@@ -576,8 +581,14 @@
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>".$args{'function'}."</refname>\n";
@@ -607,7 +618,7 @@
 	    }
 	}
     } else {
-	print "  <void>\n";
+	print "  <void/>\n";
     }
     print "  </funcprototype></funcsynopsis>\n";
     print "</refsynopsisdiv>\n";
@@ -646,8 +657,14 @@
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
@@ -724,8 +741,14 @@
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>enum ".$args{'enum'}."</refname>\n";
@@ -784,8 +807,14 @@
     $id =~ s/[^A-Za-z0-9]/-/g;
 
     print "<refentry>\n";
+    print "<refentryinfo>\n";
+    print " <title>LINUX</title>\n";
+    print " <productname>Kernel Hackers Manual</productname>\n";
+    print " <date>$man_date</date>\n";
+    print "</refentryinfo>\n";
     print "<refmeta>\n";
-    print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
+    print " <refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
+    print " <manvolnum>9</manvolnum>\n";
     print "</refmeta>\n";
     print "<refnamediv>\n";
     print " <refname>typedef ".$args{'typedef'}."</refname>\n";
@@ -1465,6 +1494,8 @@
 
     $prototype =~ s/^static +//;
     $prototype =~ s/^extern +//;
+    $prototype =~ s/^fastcall +//;
+    $prototype =~ s/^asmlinkage +//;
     $prototype =~ s/^inline +//;
     $prototype =~ s/^__inline__ +//;
     $prototype =~ s/^#define +//; #ak added
diff --git a/scripts/makeman b/scripts/makeman
deleted file mode 100755
index db3af64..0000000
--- a/scripts/makeman
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-
-## Copyright (C) Michael Still (mikal@stillhq.com)
-## Released under the terms of the GNU GPL
-##
-## A script to make or install the manpages extracted by split-man
-##
-## Arguements: $1 -- the word "convert" or "install"
-##             $2 -- the directory containing the SGML files for the manpages
-##             $3 -- the filename which contained the sgmldoc output
-##                     (I need this so I know which manpages to convert)
-
-my($LISTING, $GENERATED, $INPUT, $OUTPUT, $front, $mode, $filename, $tmpdir);
-
-if($ARGV[0] eq ""){
-  die "Usage: makeman [convert | install] <dir> <file>\n";
-}
-
-if( ! -d "$ARGV[1]" ){
-  die "Output directory \"$ARGV[1]\" does not exist\n";
-}
-
-if($ENV{"TMPDIR"} ne ""){
-  $tmpdir = $ENV{"TMPDIR"};
-}
-else{
-  $tmpdir = "/tmp";
-}
-
-if($ARGV[0] eq "convert"){
-  open LISTING, "grep \"<refentrytitle>\" $ARGV[2] |";
-  while(<LISTING>){
-    s/<\/.*$//;
-    s/^.*>//;
-    s/\.sgml//;
-    s/struct //;
-    s/typedef //;
-
-    chomp;
-    $filename = $_;
-    print "Processing $filename\n";
-
-    # Open the input file to extract the front matter, generate the man page,
-    # and open it, and the rearrange everything until it is happy
-    open INPUT, "< $ARGV[1]/$filename.sgml";
-    $front = "";
-    $mode = 0;
-
-    # The modes used here are:
-    #                                                         mode = 0
-    # <!-- BEGINFRONTTAG -->
-    # <!-- <bookinfo>                                         mode = 1
-    # <!--   <legalnotice>                                    mode = 2
-    # <!--     ...GPL or whatever...
-    # <!--   </legalnotice>                                   mode = 4
-    # <!-- </bookinfo>                                        mode = 3
-    # <!-- ENDFRONTTAG -->
-    #
-    # ...doco...
-
-    # I know that some of the if statements in this while loop are in a funny
-    # order, but that is deliberate...
-    while(<INPUT>){
-      if($mode > 0){
-	s/<!-- //;
-	s/ -->//;
-	s/<docinfo>//i;
-	s<\/docinfo>//i;
-	s/^[ \t]*//i;
-      }
-
-      if($mode == 2){
-	if(/<para>/i){
-	}
-	elsif(/<\/para>/i){
-	  $front = "$front.\\\" \n";
-	}
-	elsif(/<\/legalnotice>/i){
-	  $mode = 4;
-	}
-	elsif(/^[ \t]*$/){
-	}
-	else{
-	  $front = "$front.\\\"     $_";
-	}
-      }
-
-      if($mode == 1){
-	if(/<title>(.*)<\/title>/i){
-	  $front = "$front.\\\" This documentation was generated from the book titled \"$1\", which is part of the Linux kernel source.\n.\\\" \n";
-	}
-	elsif(/<legalnotice>/i){
-	  $front = "$front.\\\" This documentation comes with the following legal notice:\n.\\\" \n";
-	  $mode = 2;
-	}
-
-	elsif(/<author>/i){
-	  $front = "$front.\\\" Documentation by: ";
-	}
-	elsif(/<firstname>(.*)<\/firstname>/i){
-	  $front = "$front$1 ";
-	}
-	elsif(/<surname>(.*)<\/surname>/i){
-	  $front = "$front$1 ";
-	}
-	elsif(/<email>(.*)<\/email>/i){
-	  $front = "$front($1)";
-	}
-	elsif(/\/author>/i){
-	  $front = "$front\n";
-	}
-
-	elsif(/<copyright>/i){
-	  $front = "$front.\\\" Documentation copyright: ";
-	}
-	elsif(/<holder>(.*)<\/holder>/i){
-	  $front = "$front$1 ";
-	}
-	elsif(/<year>(.*)<\/year>/i){
-	  $front = "$front$1 ";
-	}
-	elsif(/\/copyright>/i){
-	  $front = "$front\n";
-	}
-
-	elsif(/^[ \t]*$/
-	      || /<affiliation>/i
-	      || /<\/affiliation>/i
-	      || /<address>/i
-	      || /<\/address>/i
-	      || /<authorgroup>/i
-	      || /<\/authorgroup>/i
-	      || /<\/legalnotice>/i
-              || /<date>/i
-              || /<\/date>/i
-              || /<edition>/i
-              || /<\/edition>/i
-	      || /<pubdate>/i
-	      || /<\/pubdate>/i){
-	}
-	else{
-	  print "Unknown tag in manpage conversion: $_";
-	  }
-      }
-
-      if($mode == 0){
-	if(/<bookinfo>/i){
-	  $mode = 1;
-	}
-      }
-
-      if($mode == 4){
-	if(/<\/bookinfo>/i){
-	  $mode = 3;
-	}
-      }
-    }
-    close INPUT;
-
-    system("cd $ARGV[1]; docbook2man $filename.sgml; mv $filename.9 $tmpdir/$$.9\n");
-    open GENERATED, "< $tmpdir/$$.9";
-    open OUTPUT, "> $ARGV[1]/$filename.9";
-
-    print OUTPUT "$front";
-    print OUTPUT ".\\\" For comments on the formatting of this manpage, please contact Michael Still <mikal\@stillhq.com>\n\n";
-    while(<GENERATED>){
-      print OUTPUT "$_";
-    }
-    close OUTPUT;
-    close GENERATED;
-
-    system("gzip -f $ARGV[1]/$filename.9\n");
-    unlink("$tmpdir/$$.9");
-  }
-}
-elsif($ARGV[0] eq "install"){
-  system("mkdir -p /usr/local/man/man9/; install $ARGV[1]/*.9.gz /usr/local/man/man9/");
-}
-else{
-  die "Usage: makeman [convert | install] <dir> <file>\n";
-}
-
-print "Done\n";
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index d54b52d..32197ef 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -47,32 +47,31 @@
                 sprintf(str + strlen(str), "*");                \
 } while(0)
 
-/* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */
-static int do_usb_entry(const char *filename,
-			struct usb_device_id *id, char *alias)
+/* USB is special because the bcdDevice can be matched against a numeric range */
+/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
+static void do_usb_entry(struct usb_device_id *id,
+			 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
+			 unsigned char range_lo, unsigned char range_hi,
+			 struct module *mod)
 {
-	id->match_flags = TO_NATIVE(id->match_flags);
-	id->idVendor = TO_NATIVE(id->idVendor);
-	id->idProduct = TO_NATIVE(id->idProduct);
-	id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo);
-	id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi);
-
-	/*
-	 * Some modules (visor) have empty slots as placeholder for
-	 * run-time specification that results in catch-all alias
-	 */
-	if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
-		return 1;
-
+	char alias[500];
 	strcpy(alias, "usb:");
 	ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
 	    id->idVendor);
 	ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
 	    id->idProduct);
-	ADD(alias, "dl", id->match_flags&USB_DEVICE_ID_MATCH_DEV_LO,
-	    id->bcdDevice_lo);
-	ADD(alias, "dh", id->match_flags&USB_DEVICE_ID_MATCH_DEV_HI,
-	    id->bcdDevice_hi);
+
+	strcat(alias, "d");
+	if (bcdDevice_initial_digits)
+		sprintf(alias + strlen(alias), "%0*X",
+			bcdDevice_initial_digits, bcdDevice_initial);
+	if (range_lo == range_hi)
+		sprintf(alias + strlen(alias), "%u", range_lo);
+	else if (range_lo > 0 || range_hi < 9)
+		sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi);
+	if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+		strcat(alias, "*");
+
 	ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
 	    id->bDeviceClass);
 	ADD(alias, "dsc",
@@ -90,7 +89,73 @@
 	ADD(alias, "ip",
 	    id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
 	    id->bInterfaceProtocol);
-	return 1;
+
+	/* Always end in a wildcard, for future extension */
+	if (alias[strlen(alias)-1] != '*')
+		strcat(alias, "*");
+	buf_printf(&mod->dev_table_buf,
+		   "MODULE_ALIAS(\"%s\");\n", alias);
+}
+
+static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
+{
+	unsigned int devlo, devhi;
+	unsigned char chi, clo;
+	int ndigits;
+
+	id->match_flags = TO_NATIVE(id->match_flags);
+	id->idVendor = TO_NATIVE(id->idVendor);
+	id->idProduct = TO_NATIVE(id->idProduct);
+
+	devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+		TO_NATIVE(id->bcdDevice_lo) : 0x0U;
+	devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+		TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
+
+	/*
+	 * Some modules (visor) have empty slots as placeholder for
+	 * run-time specification that results in catch-all alias
+	 */
+	if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
+		return;
+
+	/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
+	for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
+		clo = devlo & 0xf;
+		chi = devhi & 0xf;
+		if (chi > 9)	/* it's bcd not hex */
+			chi = 9;
+		devlo >>= 4;
+		devhi >>= 4;
+
+		if (devlo == devhi || !ndigits) {
+			do_usb_entry(id, devlo, ndigits, clo, chi, mod);
+			break;
+		}
+
+		if (clo > 0)
+			do_usb_entry(id, devlo++, ndigits, clo, 9, mod);
+
+		if (chi < 9)
+			do_usb_entry(id, devhi--, ndigits, 0, chi, mod);
+	}
+}
+
+static void do_usb_table(void *symval, unsigned long size,
+			 struct module *mod)
+{
+	unsigned int i;
+	const unsigned long id_size = sizeof(struct usb_device_id);
+
+	if (size % id_size || size < id_size) {
+		fprintf(stderr, "*** Warning: %s ids %lu bad size "
+			"(each on %lu)\n", mod->name, size, id_size);
+	}
+	/* Leave last one: it's the terminator. */
+	size -= id_size;
+
+	for (i = 0; i < size; i += id_size)
+		do_usb_entry_multi(symval + i, mod);
 }
 
 /* Looks like: ieee1394:venNmoNspNverN */
@@ -280,8 +345,8 @@
 		do_table(symval, sym->st_size, sizeof(struct pci_device_id),
 			 do_pci_entry, mod);
 	else if (sym_is(symname, "__mod_usb_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct usb_device_id),
-			 do_usb_entry, mod);
+		/* special case to handle bcdDevice ranges */
+		do_usb_table(symval, sym->st_size, mod);
 	else if (sym_is(symname, "__mod_ieee1394_device_table"))
 		do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id),
 			 do_ieee1394_entry, mod);
diff --git a/scripts/patch-kernel b/scripts/patch-kernel
index 43af010..f2d47ca 100755
--- a/scripts/patch-kernel
+++ b/scripts/patch-kernel
@@ -46,6 +46,19 @@
 # fix some whitespace damage;
 # be smarter about stopping when current version is larger than requested;
 #	Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18.
+#
+# Add better support for (non-incremental) 2.6.x.y patches;
+# If an ending version number if not specified, the script automatically
+# increments the SUBLEVEL (x in 2.6.x.y) until no more patch files are found;
+# however, EXTRAVERSION (y in 2.6.x.y) is never automatically incremented
+# but must be specified fully.
+#
+# patch-kernel does not normally support reverse patching, but does so when
+# applying EXTRAVERSION (x.y) patches, so that moving from 2.6.11.y to 2.6.11.z
+# is easy and handled by the script (reverse 2.6.11.y and apply 2.6.11.z).
+#	Randy Dunlap <rddunlap@osdl.org>, 2005-APR-08.
+
+PNAME=patch-kernel
 
 # Set directories from arguments, or use defaults.
 sourcedir=${1-/usr/src/linux}
@@ -54,7 +67,7 @@
 
 if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then
 cat << USAGE
-usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
+usage: $PNAME [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
   source directory defaults to /usr/src/linux,
   patch directory defaults to the current directory,
   stopversion defaults to <all in patchdir>.
@@ -73,6 +86,19 @@
 done
 
 # ---------------------------------------------------------------------------
+# arg1 is filename
+noFile () {
+	echo "cannot find patch file: ${patch}"
+	exit 1
+}
+
+# ---------------------------------------------------------------------------
+backwards () {
+	echo "$PNAME does not support reverse patching"
+	exit 1
+}
+
+# ---------------------------------------------------------------------------
 # Find a file, first parameter is basename of file
 # it tries many compression mechanisms and sets variables to say how to get it
 findFile () {
@@ -133,6 +159,28 @@
   return 0;
 }
 
+# ---------------------------------------------------------------------------
+# arg1 is patch filename
+reversePatch () {
+	echo -n "Reversing $1 (${name}) ... "
+	if $uncomp ${patchdir}/"$1"${ext} | patch -p1 -Rs -N -E -d $sourcedir
+	then
+		echo "done."
+	else
+		echo "failed.  Clean it up."
+		exit 1
+	fi
+	if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
+	then
+		echo "Aborting.  Reject files found."
+		return 1
+	fi
+	# Remove backup files
+	find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
+
+	return 0
+}
+
 # set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
 TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; }
 grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE
@@ -160,53 +208,57 @@
 		EXTRAVER=$EXTRAVERSION
 	fi
 	EXTRAVER=${EXTRAVER%%[[:punct:]]*}
-	#echo "patch-kernel: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER"
+	#echo "$PNAME: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER"
 fi
 
 #echo "stopvers=$stopvers"
 if [ $stopvers != "default" ]; then
 	STOPSUBLEVEL=`echo $stopvers | cut -d. -f3`
 	STOPEXTRA=`echo $stopvers | cut -d. -f4`
-	#echo "STOPSUBLEVEL=$STOPSUBLEVEL, STOPEXTRA=$STOPEXTRA"
+	#echo "#___STOPSUBLEVEL=/$STOPSUBLEVEL/, STOPEXTRA=/$STOPEXTRA/"
 else
 	STOPSUBLEVEL=9999
 	STOPEXTRA=9999
 fi
 
+# This all assumes a 2.6.x[.y] kernel tree.
+# Don't allow backwards/reverse patching.
+if [ $STOPSUBLEVEL -lt $SUBLEVEL ]; then
+	backwards
+fi
+
+if [ x$EXTRAVER != "x" ]; then
+	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+else
+	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+fi
+
+if [ x$EXTRAVER != "x" ]; then
+	echo "backing up to: $VERSION.$PATCHLEVEL.$SUBLEVEL"
+	patch="patch-${CURRENTFULLVERSION}"
+	findFile $patchdir/${patch} || noFile ${patch}
+	reversePatch ${patch} || exit 1
+fi
+
+# now current is 2.6.x, with no EXTRA applied,
+# so update to target SUBLEVEL (2.6.SUBLEVEL)
+# and then to target EXTRAVER (2.6.SUB.EXTRAVER) if requested.
+# If not ending sublevel is specified, it is incremented until
+# no further sublevels are found.
+
+if [ $STOPSUBLEVEL -gt $SUBLEVEL ]; then
 while :				# incrementing SUBLEVEL (s in v.p.s)
 do
-    if [ x$EXTRAVER != "x" ]; then
-	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
-    else
-	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
-    fi
-
+    CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    EXTRAVER=
     if [ $stopvers == $CURRENTFULLVERSION ]; then
         echo "Stopping at $CURRENTFULLVERSION base as requested."
         break
     fi
 
-    while :			# incrementing EXTRAVER (x in v.p.s.x)
-    do
-	EXTRAVER=$((EXTRAVER + 1))
-	FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
-	#echo "... trying $FULLVERSION ..."
-
-	patch=patch-$FULLVERSION
-
-	# See if the file exists and find extension
-	findFile $patchdir/${patch} || break
-
-	# Apply the patch and check all is OK
-	applyPatch $patch || break
-
-	continue 2
-    done
-
-    EXTRAVER=
     SUBLEVEL=$((SUBLEVEL + 1))
     FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
-    #echo "___ trying $FULLVERSION ___"
+    #echo "#___ trying $FULLVERSION ___"
 
     if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then
 	echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)"
@@ -214,14 +266,33 @@
     fi
 
     patch=patch-$FULLVERSION
-
     # See if the file exists and find extension
-    findFile $patchdir/${patch} || break
+    findFile $patchdir/${patch} || noFile ${patch}
 
     # Apply the patch and check all is OK
     applyPatch $patch || break
 done
-#echo "base all done"
+#echo "#___sublevel all done"
+fi
+
+# There is no incremental searching for extraversion...
+if [ "$STOPEXTRA" != "" ]; then
+while :				# just to allow break
+do
+# apply STOPEXTRA directly (not incrementally) (x in v.p.s.x)
+	FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$STOPEXTRA"
+	#echo "#... trying $FULLVERSION ..."
+	patch=patch-$FULLVERSION
+
+	# See if the file exists and find extension
+	findFile $patchdir/${patch} || noFile ${patch}
+
+	# Apply the patch and check all is OK
+	applyPatch $patch || break
+	#echo "#___extraver all done"
+	break
+done
+fi
 
 if [ x$gotac != x ]; then
   # Out great user wants the -ac patches
diff --git a/scripts/split-man b/scripts/split-man
deleted file mode 100755
index 03897fe..0000000
--- a/scripts/split-man
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-
-## Copyright (C) Michael Still (mikal@stillhq.com)
-## Released under the terms of the GNU GPL
-##
-## Hoon through the specified DocBook SGML file, and split out the
-## man pages. These can then be processed into groff format, and
-## installed if desired...
-##
-## Arguements: $1 -- the name of the sgml file
-##             $2 -- the directory to put the generated SGML files in
-##             $3 -- kernel version
-
-my($SGML, $REF, $front, $refdata, $mode, $filename);
-
-if(($ARGV[0] eq "") || ($ARGV[1] eq "") || ($ARGV[2] eq "")){
-  die "Usage: split-man <sgml file> <output dir> <kernel version>\n";
-}
-
-open SGML, "< $ARGV[0]" or die "Could not open input file \"$ARGV[0]\"\n";
-if( ! -d "$ARGV[1]" ){
-  die "Output directory \"$ARGV[1]\" does not exist\n";
-}
-
-# Possible modes:
-#   0: Looking for input I care about
-#   1: Inside book front matter
-#   2: Inside a refentry
-#   3: Inside a refentry, and we know the filename
-
-$mode = 0;
-$refdata = "";
-$front = "";
-while(<SGML>){
-  # Starting modes
-  if(/<bookinfo>/ || /<docinfo>/){
-    $mode = 1;
-  }
-  elsif(/<refentry>/){
-    $mode = 2;
-  }
-  elsif(/<refentrytitle><phrase[^>]*>([^<]*)<.*$/){
-    $mode = 3;
-    $filename = $1;
-
-    $filename =~ s/struct //;
-    $filename =~ s/typedef //;
-
-    print "Found manpage for $filename\n";
-    open REF, "> $ARGV[1]/$filename.sgml" or
-      die "Couldn't open output file \"$ARGV[1]/$filename.sgml\": $!\n";
-    print REF <<EOF;
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<!-- BEGINFRONTTAG: The following is front matter for the parent book -->
-$front
-<!-- ENDFRONTTAG: End front matter -->
-
-$refdata
-EOF
-    $refdata = "";
-  }
-
-  # Extraction
-  if($mode == 1){
-    chomp $_;
-    $front = "$front<!-- $_ -->\n";
-  }
-  elsif($mode == 2){
-    $refdata = "$refdata$_";
-  }
-  elsif($mode == 3){
-    # There are some fixups which need to be applied
-    if(/<\/refmeta>/){
-      print REF "<manvolnum>9</manvolnum>\n";
-    }
-    if(/<\/refentry>/){
-      print REF <<EOF;
-<refsect1><title>About this document</title>
-<para>
-This documentation was generated with kernel version $ARGV[2].
-</para>
-</refsect1>
-EOF
-    }
-
-    # For some reason, we title the synopsis twice in the main DocBook
-    if(! /<title>Synopsis<\/title>/){
-      if(/<refentrytitle>/){
-	s/struct //;
-	s/typedef //;
-      }
-
-      print REF "$_";
-    }
-  }
-
-  # Ending modes
-  if(/<\/bookinfo>/ || /<\/docinfo>/){
-    $mode = 0;
-  }
-  elsif(/<\/refentry>/){
-    $mode = 0;
-    close REF;
-  }
-}
-
-# And make sure we don't process this unnessesarily
-$ARGV[0] =~ s/\.sgml/.9/;
-`touch $ARGV[0]`;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2ae7d3c..aae1e79 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2855,8 +2855,7 @@
 
 	nexthdr = ip6->nexthdr;
 	offset += sizeof(_ipv6h);
-	offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
-				  skb->tail - skb->head - offset);
+	offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
 	if (offset < 0)
 		goto out;
 
@@ -3668,7 +3667,7 @@
 }
 
 static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
-			u16 sclass, u32 perms)
+			u32 perms)
 {
 	struct task_security_struct *tsec;
 	struct ipc_security_struct *isec;
@@ -3680,7 +3679,7 @@
 	AVC_AUDIT_DATA_INIT(&ad, IPC);
 	ad.u.ipc_id = ipc_perms->key;
 
-	return avc_has_perm(tsec->sid, isec->sid, sclass, perms, &ad);
+	return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
 }
 
 static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
@@ -3765,7 +3764,7 @@
 		return 0;
 	}
 
-	err = ipc_has_perm(&msq->q_perm, SECCLASS_MSGQ, perms);
+	err = ipc_has_perm(&msq->q_perm, perms);
 	return err;
 }
 
@@ -3917,7 +3916,7 @@
 		return 0;
 	}
 
-	err = ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms);
+	err = ipc_has_perm(&shp->shm_perm, perms);
 	return err;
 }
 
@@ -3936,7 +3935,7 @@
 	else
 		perms = SHM__READ | SHM__WRITE;
 
-	return ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms);
+	return ipc_has_perm(&shp->shm_perm, perms);
 }
 
 /* Semaphore security operations */
@@ -4025,7 +4024,7 @@
 		return 0;
 	}
 
-	err = ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms);
+	err = ipc_has_perm(&sma->sem_perm, perms);
 	return err;
 }
 
@@ -4039,18 +4038,13 @@
 	else
 		perms = SEM__READ;
 
-	return ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms);
+	return ipc_has_perm(&sma->sem_perm, perms);
 }
 
 static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 {
-	struct ipc_security_struct *isec = ipcp->security;
-	u16 sclass = SECCLASS_IPC;
 	u32 av = 0;
 
-	if (isec && isec->magic == SELINUX_MAGIC)
-		sclass = isec->sclass;
-
 	av = 0;
 	if (flag & S_IRUGO)
 		av |= IPC__UNIX_READ;
@@ -4060,7 +4054,7 @@
 	if (av == 0)
 		return 0;
 
-	return ipc_has_perm(ipcp, sclass, av);
+	return ipc_has_perm(ipcp, av);
 }
 
 /* module stacking operations */
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index eb340b4..8928bb4d 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -220,6 +220,8 @@
    S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write")
    S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read")
    S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write")
+   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay")
+   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv")
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read")
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write")
    S_(SECCLASS_DBUS, DBUS__ACQUIRE_SVC, "acquire_svc")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index f9de0f96..bdfce4c 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -840,6 +840,8 @@
 
 #define NETLINK_AUDIT_SOCKET__NLMSG_READ          0x00400000UL
 #define NETLINK_AUDIT_SOCKET__NLMSG_WRITE         0x00800000UL
+#define NETLINK_AUDIT_SOCKET__NLMSG_RELAY         0x01000000UL
+#define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV      0x02000000UL
 
 #define NETLINK_IP6FW_SOCKET__IOCTL               0x00000001UL
 #define NETLINK_IP6FW_SOCKET__READ                0x00000002UL
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index f794082..b3adb48 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -91,13 +91,12 @@
 
 static struct nlmsg_perm nlmsg_audit_perms[] =
 {
-	{ AUDIT_GET,		NETLINK_AUDIT_SOCKET__NLMSG_READ  },
-	{ AUDIT_SET,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
-	{ AUDIT_LIST,		NETLINK_AUDIT_SOCKET__NLMSG_READ  },
-	{ AUDIT_ADD,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
-	{ AUDIT_DEL,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
-	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
-	{ AUDIT_LOGIN,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+	{ AUDIT_GET,		NETLINK_AUDIT_SOCKET__NLMSG_READ     },
+	{ AUDIT_SET,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
+	{ AUDIT_LIST,		NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
+	{ AUDIT_ADD,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
+	{ AUDIT_DEL,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
+	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
 };
 
 
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 4a6be96..3a3228b 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -164,6 +164,7 @@
 	select SND_RAWMIDI
 	select SND_CS4231_LIB
 	select SND_GUS_SYNTH
+	select ISAPNP
 	help
 	  Say Y here to include support for AMD InterWave based
 	  soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index 124b1e1..3ecef46 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -155,6 +155,7 @@
 	{0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
 	{0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
 	{0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
+	{0x43585430, "CXT48",			&default_ops,		AC97_DELUDED_MODEM },
 	{0x43585442, "CXT66",			&default_ops,		AC97_DELUDED_MODEM },
 	{0x44543031, "Diamond Technology DT0893", &default_ops},
 	{0x45838308, "ESS Allegro ES1988",	&null_ops},
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 6ba03f8..0c2db65 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -892,7 +892,7 @@
 static int dsp_read(char __user *buf, size_t len)
 {
 	int count = len;
-	char *page = (char *)__get_free_page(PAGE_SIZE);
+	char *page = (char *)__get_free_page(GFP_KERNEL);
 
 	if (!page)
 		return -ENOMEM;
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
index e1d6961..06047e7 100644
--- a/sound/oss/sonicvibes.c
+++ b/sound/oss/sonicvibes.c
@@ -1149,7 +1149,7 @@
 			if (mixtable[i].rec)
 				break;
 		}
-		if (!mixtable[i].rec)
+		if (i == SOUND_MIXER_NRDEVICES)
 			return 0;
 		spin_lock_irqsave(&s->lock, flags);
 		frobindir(s, SV_CIMIX_ADCINL, 0x1f, mixtable[i].rec << 5);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d89647a..959953c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -64,7 +64,8 @@
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
 			 "{Intel, ICH6M},"
-			 "{Intel, ICH7}}");
+			 "{Intel, ICH7},"
+			 "{Intel, ESB2}}");
 MODULE_DESCRIPTION("Intel HDA driver");
 
 #define SFX	"hda-intel: "
@@ -1422,6 +1423,7 @@
 static struct pci_device_id azx_ids[] = {
 	{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
 	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
+	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index d143d2c..8b33b12 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -125,8 +125,8 @@
 #ifndef PCI_DEVICE_ID_INTEL_ICH7_20
 #define PCI_DEVICE_ID_INTEL_ICH7_20	0x27de
 #endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB2_13
-#define PCI_DEVICE_ID_INTEL_ESB2_13	0x2698
+#ifndef PCI_DEVICE_ID_INTEL_ESB2_14
+#define PCI_DEVICE_ID_INTEL_ESB2_14	0x2698
 #endif
 #ifndef PCI_DEVICE_ID_SI_7012
 #define PCI_DEVICE_ID_SI_7012		0x7012
@@ -2741,7 +2741,7 @@
 	{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
 	{ PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
 	{ PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
-	{ PCI_DEVICE_ID_INTEL_ESB2_13, "Intel ESB2" },
+	{ PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" },
 	{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index f1ce808..9b4d74d 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1836,7 +1836,7 @@
  *
  */
 
-static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
+static int snd_via82xx_chip_init(via82xx_t *chip)
 {
 	unsigned int val;
 	int max_count;
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index b0a9ebf..75213bf 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -11,7 +11,7 @@
 
 config SND_POWERMAC
 	tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
-	depends on SND && I2C && INPUT
+	depends on SND && I2C && INPUT && PPC_PMAC
 	select SND_PCM
 	help
 	  Say Y here to include support for the integrated sound device.
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
index 4d95c65..d6ba995 100644
--- a/sound/ppc/Makefile
+++ b/sound/ppc/Makefile
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
+snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o toonie.o keywest.o beep.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 3bf5f06..32d9475 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -986,7 +986,13 @@
 			chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 			chip->model = PMAC_SNAPPER;
 			chip->can_byte_swap = 0; /* FIXME: check this */
-			chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
+			chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
+			break;
+		case 0x3a:
+			chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
+			chip->model = PMAC_TOONIE;
+			chip->can_byte_swap = 0; /* FIXME: check this */
+			chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
 			break;
 		}
 	}
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h
index dc6c99d..0a84c05 100644
--- a/sound/ppc/pmac.h
+++ b/sound/ppc/pmac.h
@@ -94,7 +94,8 @@
  */
 
 enum snd_pmac_model {
-	PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, PMAC_SNAPPER
+	PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER,
+	PMAC_SNAPPER, PMAC_TOONIE
 };
 
 struct snd_pmac {
@@ -191,6 +192,7 @@
 int snd_pmac_daca_init(pmac_t *chip);
 int snd_pmac_tumbler_init(pmac_t *chip);
 int snd_pmac_tumbler_post_init(void);
+int snd_pmac_toonie_init(pmac_t *chip);
 
 /* i2c functions */
 typedef struct snd_pmac_keywest {
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 8f1953a..231f643 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -95,6 +95,13 @@
 		if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0)
 			goto __error;
 		break;
+	case PMAC_TOONIE:
+		strcpy(card->driver, "PMac Toonie");
+		strcpy(card->shortname, "PowerMac Toonie");
+		strcpy(card->longname, card->shortname);
+		if ((err = snd_pmac_toonie_init(chip)) < 0)
+			goto __error;
+		break;
 	case PMAC_AWACS:
 	case PMAC_SCREAMER:
 		name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS";
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c
new file mode 100644
index 0000000..082bc4b
--- /dev/null
+++ b/sound/ppc/toonie.c
@@ -0,0 +1,379 @@
+/*
+ * Mac Mini "toonie" mixer control
+ *
+ * Copyright (c) 2005 by Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <sound/core.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include "pmac.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+struct pmac_gpio {
+	unsigned int addr;
+	u8 active_val;
+	u8 inactive_val;
+	u8 active_state;
+};
+
+struct pmac_toonie
+{
+	struct pmac_gpio	hp_detect_gpio;
+	struct pmac_gpio	hp_mute_gpio;
+	struct pmac_gpio	amp_mute_gpio;
+	int			hp_detect_irq;
+	int			auto_mute_notify;
+	struct work_struct	detect_work;
+};
+
+
+/*
+ * gpio access
+ */
+#define do_gpio_write(gp, val) \
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)
+#define do_gpio_read(gp) \
+	pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
+#define tumbler_gpio_free(gp) /* NOP */
+
+static void write_audio_gpio(struct pmac_gpio *gp, int active)
+{
+	if (! gp->addr)
+		return;
+	active = active ? gp->active_val : gp->inactive_val;
+	do_gpio_write(gp, active);
+	DBG("(I) gpio %x write %d\n", gp->addr, active);
+}
+
+static int check_audio_gpio(struct pmac_gpio *gp)
+{
+	int ret;
+
+	if (! gp->addr)
+		return 0;
+
+	ret = do_gpio_read(gp);
+
+	return (ret & 0xd) == (gp->active_val & 0xd);
+}
+
+static int read_audio_gpio(struct pmac_gpio *gp)
+{
+	int ret;
+	if (! gp->addr)
+		return 0;
+	ret = ((do_gpio_read(gp) & 0x02) !=0);
+	return ret == gp->active_state;
+}
+
+
+enum { TOONIE_MUTE_HP, TOONIE_MUTE_AMP };
+
+static int toonie_get_mute_switch(snd_kcontrol_t *kcontrol,
+				  snd_ctl_elem_value_t *ucontrol)
+{
+	pmac_t *chip = snd_kcontrol_chip(kcontrol);
+	struct pmac_toonie *mix = chip->mixer_data;
+	struct pmac_gpio *gp;
+
+	if (mix == NULL)
+		return -ENODEV;
+	switch(kcontrol->private_value) {
+	case TOONIE_MUTE_HP:
+		gp = &mix->hp_mute_gpio;
+		break;
+	case TOONIE_MUTE_AMP:
+		gp = &mix->amp_mute_gpio;
+		break;
+	default:
+		return -EINVAL;;
+	}
+	ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
+	return 0;
+}
+
+static int toonie_put_mute_switch(snd_kcontrol_t *kcontrol,
+				   snd_ctl_elem_value_t *ucontrol)
+{
+	pmac_t *chip = snd_kcontrol_chip(kcontrol);
+	struct pmac_toonie *mix = chip->mixer_data;
+	struct pmac_gpio *gp;
+	int val;
+
+	if (chip->update_automute && chip->auto_mute)
+		return 0; /* don't touch in the auto-mute mode */
+
+	if (mix == NULL)
+		return -ENODEV;
+
+	switch(kcontrol->private_value) {
+	case TOONIE_MUTE_HP:
+		gp = &mix->hp_mute_gpio;
+		break;
+	case TOONIE_MUTE_AMP:
+		gp = &mix->amp_mute_gpio;
+		break;
+	default:
+		return -EINVAL;;
+	}
+	val = ! check_audio_gpio(gp);
+	if (val != ucontrol->value.integer.value[0]) {
+		write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
+		return 1;
+	}
+	return 0;
+}
+
+static snd_kcontrol_new_t toonie_hp_sw __initdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Headphone Playback Switch",
+	.info = snd_pmac_boolean_mono_info,
+	.get = toonie_get_mute_switch,
+	.put = toonie_put_mute_switch,
+	.private_value = TOONIE_MUTE_HP,
+};
+static snd_kcontrol_new_t toonie_speaker_sw __initdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "PC Speaker Playback Switch",
+	.info = snd_pmac_boolean_mono_info,
+	.get = toonie_get_mute_switch,
+	.put = toonie_put_mute_switch,
+	.private_value = TOONIE_MUTE_AMP,
+};
+
+/*
+ * auto-mute stuffs
+ */
+static int toonie_detect_headphone(pmac_t *chip)
+{
+	struct pmac_toonie *mix = chip->mixer_data;
+	int detect = 0;
+
+	if (mix->hp_detect_gpio.addr)
+		detect |= read_audio_gpio(&mix->hp_detect_gpio);
+	return detect;
+}
+
+static void toonie_check_mute(pmac_t *chip, struct pmac_gpio *gp, int val,
+			      int do_notify, snd_kcontrol_t *sw)
+{
+	if (check_audio_gpio(gp) != val) {
+		write_audio_gpio(gp, val);
+		if (do_notify)
+			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+				       &sw->id);
+	}
+}
+
+static void toonie_detect_handler(void *self)
+{
+	pmac_t *chip = (pmac_t*) self;
+	struct pmac_toonie *mix;
+	int headphone;
+
+	if (!chip)
+		return;
+
+	mix = chip->mixer_data;
+	snd_assert(mix, return);
+
+	headphone = toonie_detect_headphone(chip);
+
+	DBG("headphone: %d, lineout: %d\n", headphone, lineout);
+
+	if (headphone) {
+		/* unmute headphone/lineout & mute speaker */
+		toonie_check_mute(chip, &mix->hp_mute_gpio, 0,
+				  mix->auto_mute_notify, chip->master_sw_ctl);
+		toonie_check_mute(chip, &mix->amp_mute_gpio, 1,
+				  mix->auto_mute_notify, chip->speaker_sw_ctl);
+	} else {
+		/* unmute speaker, mute others */
+		toonie_check_mute(chip, &mix->amp_mute_gpio, 0,
+				  mix->auto_mute_notify, chip->speaker_sw_ctl);
+		toonie_check_mute(chip, &mix->hp_mute_gpio, 1,
+				  mix->auto_mute_notify, chip->master_sw_ctl);
+	}
+	if (mix->auto_mute_notify) {
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+				       &chip->hp_detect_ctl->id);
+	}
+}
+
+static void toonie_update_automute(pmac_t *chip, int do_notify)
+{
+	if (chip->auto_mute) {
+		struct pmac_toonie *mix;
+		mix = chip->mixer_data;
+		snd_assert(mix, return);
+		mix->auto_mute_notify = do_notify;
+		schedule_work(&mix->detect_work);
+	}
+}
+
+/* interrupt - headphone plug changed */
+static irqreturn_t toonie_hp_intr(int irq, void *devid, struct pt_regs *regs)
+{
+	pmac_t *chip = devid;
+
+	if (chip->update_automute && chip->initialized) {
+		chip->update_automute(chip, 1);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/* look for audio gpio device */
+static int find_audio_gpio(const char *name, const char *platform,
+			   struct pmac_gpio *gp)
+{
+	struct device_node *np;
+  	u32 *base, addr;
+
+	if (! (np = find_devices("gpio")))
+		return -ENODEV;
+
+	for (np = np->child; np; np = np->sibling) {
+		char *property = get_property(np, "audio-gpio", NULL);
+		if (property && strcmp(property, name) == 0)
+			break;
+		if (device_is_compatible(np, name))
+			break;
+	}
+	if (np == NULL)
+		return -ENODEV;
+
+	base = (u32 *)get_property(np, "AAPL,address", NULL);
+	if (! base) {
+		base = (u32 *)get_property(np, "reg", NULL);
+		if (!base) {
+			DBG("(E) cannot find address for device %s !\n", name);
+			return -ENODEV;
+		}
+		addr = *base;
+		if (addr < 0x50)
+			addr += 0x50;
+	} else
+		addr = *base;
+
+	gp->addr = addr & 0x0000ffff;
+
+	/* Try to find the active state, default to 0 ! */
+	base = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
+	if (base) {
+		gp->active_state = *base;
+		gp->active_val = (*base) ? 0x5 : 0x4;
+		gp->inactive_val = (*base) ? 0x4 : 0x5;
+	} else {
+		u32 *prop = NULL;
+		gp->active_state = 0;
+		gp->active_val = 0x4;
+		gp->inactive_val = 0x5;
+		/* Here are some crude hacks to extract the GPIO polarity and
+		 * open collector informations out of the do-platform script
+		 * as we don't yet have an interpreter for these things
+		 */
+		if (platform)
+			prop = (u32 *)get_property(np, platform, NULL);
+		if (prop) {
+			if (prop[3] == 0x9 && prop[4] == 0x9) {
+				gp->active_val = 0xd;
+				gp->inactive_val = 0xc;
+			}
+			if (prop[3] == 0x1 && prop[4] == 0x1) {
+				gp->active_val = 0x5;
+				gp->inactive_val = 0x4;
+			}
+		}
+	}
+
+	DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",
+	    name, gp->addr, gp->active_state);
+
+	return (np->n_intrs > 0) ? np->intrs[0].line : 0;
+}
+
+static void toonie_cleanup(pmac_t *chip)
+{
+	struct pmac_toonie *mix = chip->mixer_data;
+	if (! mix)
+		return;
+	if (mix->hp_detect_irq >= 0)
+		free_irq(mix->hp_detect_irq, chip);
+	kfree(mix);
+	chip->mixer_data = NULL;
+}
+
+int snd_pmac_toonie_init(pmac_t *chip)
+{
+	struct pmac_toonie *mix;
+
+	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
+	if (! mix)
+		return -ENOMEM;
+
+	chip->mixer_data = mix;
+	chip->mixer_free = toonie_cleanup;
+
+	find_audio_gpio("headphone-mute", NULL, &mix->hp_mute_gpio);
+	find_audio_gpio("amp-mute", NULL, &mix->amp_mute_gpio);
+	mix->hp_detect_irq = find_audio_gpio("headphone-detect",
+					     NULL, &mix->hp_detect_gpio);
+
+	strcpy(chip->card->mixername, "PowerMac Toonie");
+
+	chip->master_sw_ctl = snd_ctl_new1(&toonie_hp_sw, chip);
+	snd_ctl_add(chip->card, chip->master_sw_ctl);
+
+	chip->speaker_sw_ctl = snd_ctl_new1(&toonie_speaker_sw, chip);
+	snd_ctl_add(chip->card, chip->speaker_sw_ctl);
+
+	INIT_WORK(&mix->detect_work, toonie_detect_handler, (void *)chip);
+
+	if (mix->hp_detect_irq >= 0) {
+		snd_pmac_add_automute(chip);
+
+		chip->detect_headphone = toonie_detect_headphone;
+		chip->update_automute = toonie_update_automute;
+		toonie_update_automute(chip, 0);
+
+		if (request_irq(mix->hp_detect_irq, toonie_hp_intr, 0,
+				"Sound Headphone Detection", chip) < 0)
+			mix->hp_detect_irq = -1;
+	}
+
+	return 0;
+}
+
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index c71807e..9332237 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -99,6 +99,7 @@
 	pmac_gpio_t hp_detect;
 	int headphone_irq;
 	int lineout_irq;
+	unsigned int save_master_vol[2];
 	unsigned int master_vol[2];
 	unsigned int save_master_switch[2];
 	unsigned int master_switch[2];
@@ -177,11 +178,22 @@
 	if (! gp->addr)
 		return;
 	active = active ? gp->active_val : gp->inactive_val;
-
 	do_gpio_write(gp, active);
 	DBG("(I) gpio %x write %d\n", gp->addr, active);
 }
 
+static int check_audio_gpio(pmac_gpio_t *gp)
+{
+	int ret;
+
+	if (! gp->addr)
+		return 0;
+
+	ret = do_gpio_read(gp);
+
+	return (ret & 0xd) == (gp->active_val & 0xd);
+}
+
 static int read_audio_gpio(pmac_gpio_t *gp)
 {
 	int ret;
@@ -683,7 +695,7 @@
 	}
 	if (gp == NULL)
 		return -EINVAL;
-	ucontrol->value.integer.value[0] = ! read_audio_gpio(gp);
+	ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
 	return 0;
 }
 
@@ -711,7 +723,7 @@
 	}
 	if (gp == NULL)
 		return -EINVAL;
-	val = ! read_audio_gpio(gp);
+	val = ! check_audio_gpio(gp);
 	if (val != ucontrol->value.integer.value[0]) {
 		write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
 		return 1;
@@ -897,11 +909,11 @@
 
 static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw)
 {
-	//pmac_tumbler_t *mix = chip->mixer_data;
-	if (val != read_audio_gpio(gp)) {
+	if (check_audio_gpio(gp) != val) {
 		write_audio_gpio(gp, val);
 		if (do_notify)
-			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &sw->id);
+			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+				       &sw->id);
 	}
 }
 
@@ -1128,6 +1140,8 @@
 		disable_irq(mix->lineout_irq);
 	mix->save_master_switch[0] = mix->master_switch[0];
 	mix->save_master_switch[1] = mix->master_switch[1];
+	mix->save_master_vol[0] = mix->master_vol[0];
+	mix->save_master_vol[1] = mix->master_vol[1];
 	mix->master_switch[0] = mix->master_switch[1] = 0;
 	tumbler_set_master_volume(mix);
 	if (!mix->anded_reset) {
@@ -1155,6 +1169,8 @@
 	mix->acs &= ~1;
 	mix->master_switch[0] = mix->save_master_switch[0];
 	mix->master_switch[1] = mix->save_master_switch[1];
+	mix->master_vol[0] = mix->save_master_vol[0];
+	mix->master_vol[1] = mix->save_master_vol[1];
 	tumbler_reset_audio(chip);
 	if (mix->i2c.client && mix->i2c.init_client) {
 		if (mix->i2c.init_client(&mix->i2c) < 0)